using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Text.Json;
using Tiku.Application.Growth;

namespace Tiku.Api.Contracts;

public sealed class ReferralTenantQueryDto
{
    [StringLength(100)]
    public string? TenantCode { get; set; }
}

public sealed class ReferralInviteDto
{
    [StringLength(100)]
    public string? Channel { get; set; }

    [StringLength(2048)]
    public string? LandingPath { get; set; }

    public ReferralInviteCommand ToCommand()
    {
        return new ReferralInviteCommand(Channel, LandingPath);
    }
}

public sealed class ResolveReferralDto
{
    [StringLength(100)]
    public string? Code { get; set; }

    [StringLength(100)]
    public string? TenantCode { get; set; }

    public ResolveReferralCommand ToCommand()
    {
        return new ResolveReferralCommand(Code);
    }
}

public sealed class TrackReferralEventDto
{
    [Required]
    [StringLength(100)]
    public string RefCode { get; set; } = string.Empty;

    [StringLength(100)]
    public string? EventType { get; set; }

    [StringLength(100)]
    public string? Source { get; set; }

    public Guid? TargetUserId { get; set; }

    public JsonElement? Metadata { get; set; }

    [StringLength(100)]
    public string? TenantCode { get; set; }

    public TrackReferralEventCommand ToCommand()
    {
        return new TrackReferralEventCommand(RefCode, EventType, Source, TargetUserId, Metadata);
    }
}

public sealed class BindReferralDto
{
    [Required]
    [StringLength(100)]
    public string RefCode { get; set; } = string.Empty;

    [StringLength(100)]
    public string? Source { get; set; }

    public JsonElement? Metadata { get; set; }

    public BindReferralCommand ToCommand()
    {
        return new BindReferralCommand(RefCode, Source, Metadata);
    }
}

public sealed class ReferralQrcodeDto
{
    [StringLength(500)]
    public string? Page { get; set; }

    [StringLength(128)]
    public string? Scene { get; set; }

    [StringLength(100)]
    public string? Provider { get; set; }

    [StringLength(2048)]
    public string? QrcodeUrl { get; set; }

    public JsonElement? Metadata { get; set; }

    public ReferralQrcodeCommand ToCommand()
    {
        return new ReferralQrcodeCommand(Page, Scene, Provider, QrcodeUrl, Metadata);
    }
}

public sealed class ReferralStatsQueryDto
{
    public Guid? ReferrerUserId { get; set; }

    [Range(1, 500)]
    public int? Limit { get; set; }

    public ReferralStatsQuery ToQuery()
    {
        return new ReferralStatsQuery(ReferrerUserId, Limit);
    }
}

public sealed class ReferralConversionQueryDto
{
    public Guid? ReferrerUserId { get; set; }

    [RegularExpression("^\\d{4}-\\d{2}-\\d{2}$")]
    public string? StartDate { get; set; }

    [RegularExpression("^\\d{4}-\\d{2}-\\d{2}$")]
    public string? EndDate { get; set; }

    [Range(1, 365)]
    public int? Days { get; set; }

    [Range(1, 100)]
    public int? Limit { get; set; }

    public ReferralConversionQuery ToQuery()
    {
        return new ReferralConversionQuery(
            ReferrerUserId,
            ParseDate(StartDate),
            ParseDate(EndDate),
            Days,
            Limit);
    }

    private static DateOnly? ParseDate(string? value)
    {
        return string.IsNullOrWhiteSpace(value)
            ? null
            : DateOnly.ParseExact(value, "yyyy-MM-dd", CultureInfo.InvariantCulture);
    }
}

public sealed class ManualBindReferralDto
{
    [Required]
    public Guid StudentUserId { get; set; }

    [Required]
    public Guid ReferrerUserId { get; set; }

    [StringLength(100)]
    public string? Source { get; set; }

    public bool Force { get; set; }

    public JsonElement? Metadata { get; set; }

    public ManualBindReferralCommand ToCommand()
    {
        return new ManualBindReferralCommand(StudentUserId, ReferrerUserId, Source, Force, Metadata);
    }
}

public sealed class ReferralTeamQueryDto
{
    public Guid? LeaderUserId { get; set; }

    public ReferralTeamQuery ToQuery()
    {
        return new ReferralTeamQuery(LeaderUserId);
    }
}

public sealed class UpsertReferralTeamDto
{
    [Required]
    public Guid MemberUserId { get; set; }

    public Guid? LeaderUserId { get; set; }

    [StringLength(50)]
    public string? RelationType { get; set; }

    [StringLength(50)]
    public string? Status { get; set; }

    public JsonElement? Metadata { get; set; }

    public UpsertReferralTeamCommand ToCommand()
    {
        return new UpsertReferralTeamCommand(MemberUserId, LeaderUserId, RelationType, Status, Metadata);
    }
}
