using System.Text.Json;
using System.Text.Json.Serialization;

namespace PowderCoating.Application.DTOs.Columbia;

/// <summary>
/// One page of the Columbia Coatings <c>GET /products</c> response: a list of products plus
/// pagination metadata. Property names are snake_case in the API and bound via the snake-case
/// naming policy configured on the client's <see cref="JsonSerializerOptions"/>.
/// </summary>
public class ColumbiaProductsResponse
{
    public List<ColumbiaProduct> Items { get; set; } = new();
    public ColumbiaPagination? Pagination { get; set; }
}

/// <summary>Pagination block returned alongside a product page.</summary>
public class ColumbiaPagination
{
    public int Page { get; set; }
    public int PerPage { get; set; }
    public int Total { get; set; }
    public int TotalPages { get; set; }
}

/// <summary>
/// A single Columbia Coatings product as returned by the API. This mirrors the wire shape, not our
/// catalog model — mapping into <c>PowderCatalogItem</c> happens in the sync mapper. Prices arrive
/// as strings; cure/spec fields are free text; documents are direct URLs.
/// </summary>
public class ColumbiaProduct
{
    public int Id { get; set; }

    /// <summary>"simple" or "variable". Variable products carry packaging/size variants in
    /// <see cref="VariationPricing"/> and leave <see cref="TieredPricing"/> as an empty array.</summary>
    public string ProductType { get; set; } = string.Empty;

    public string Name { get; set; } = string.Empty;
    public string Slug { get; set; } = string.Empty;
    public string Sku { get; set; } = string.Empty;
    public string Permalink { get; set; } = string.Empty;
    public string Status { get; set; } = string.Empty;

    /// <summary>Columbia-specific values seen include "In Stock"/"instock", "formulated",
    /// "drop_shipped", "multiple_variations", "outofstock", "onbackorder" — mixed casing.</summary>
    public string StockStatus { get; set; } = string.Empty;

    // ── Pricing (all strings on the wire) ─────────────────────────────────
    public string Price { get; set; } = string.Empty;
    public string RegularPrice { get; set; } = string.Empty;
    public string SalePrice { get; set; } = string.Empty;

    /// <summary>
    /// Quantity-break pricing. POLYMORPHIC on the wire: an object
    /// (<c>{type, minimum_quantity, tiers:[...]}</c>) on simple products, but an empty ARRAY
    /// (<c>[]</c>) on variable products. Captured as a nullable raw <see cref="JsonElement"/> so
    /// deserialization never throws on the type mismatch and an absent value is null (not an
    /// invalid <c>Undefined</c> element); the mapper interprets it.
    /// </summary>
    public JsonElement? TieredPricing { get; set; }

    /// <summary>Per-variant pricing for variable products (e.g. Bulk vs 1 lb Bags, or gram sizes).
    /// Each variant has its own SKU and price. Empty for simple products.</summary>
    public List<ColumbiaVariationPricing>? VariationPricing { get; set; }

    // ── Documents (direct URLs) ───────────────────────────────────────────
    public string SafetyDataSheet { get; set; } = string.Empty;
    public string TechnicalDataSheet { get; set; } = string.Empty;
    public string ProductFlyer { get; set; } = string.Empty;
    public string ProductBrochure { get; set; } = string.Empty;

    // ── Coating spec free-text ────────────────────────────────────────────
    public string CureSchedule { get; set; } = string.Empty;
    public string MilThickness { get; set; } = string.Empty;

    /// <summary>Resin chemistry (e.g. "Polyester/TGIC", "TGIC", "Epoxy"). NOT finish/gloss.</summary>
    public string Type { get; set; } = string.Empty;

    public string ReleaseDate { get; set; } = string.Empty;
    public string FormulationDate { get; set; } = string.Empty;

    /// <summary>Free-text reformulation log, e.g. "Formulation Change: 05/22/26".</summary>
    public string FormulationDateChanges { get; set; } = string.Empty;

    // ── Content ───────────────────────────────────────────────────────────
    /// <summary>HTML product description (WordPress markup).</summary>
    public string Description { get; set; } = string.Empty;
    public string ShortDescription { get; set; } = string.Empty;

    public ColumbiaImage? FeaturedImage { get; set; }

    // ── Taxonomy (arrays of {name}) — used at import to derive manufacturer/category, not stored raw ──
    public List<ColumbiaNamed> Categories { get; set; } = new();
    public List<ColumbiaNamed> Tags { get; set; } = new();
    public List<ColumbiaNamed> PaColorGroup { get; set; } = new();
    public List<ColumbiaAttribute> Attributes { get; set; } = new();
}

/// <summary>A pricing variant of a variable product (own SKU, own price/tiers).</summary>
public class ColumbiaVariationPricing
{
    public int Id { get; set; }
    public string Sku { get; set; } = string.Empty;
    public List<ColumbiaAttributeValue> Attributes { get; set; } = new();
    public string StockStatus { get; set; } = string.Empty;
    public string Price { get; set; } = string.Empty;
    public string RegularPrice { get; set; } = string.Empty;
    public string SalePrice { get; set; } = string.Empty;

    /// <summary>Same polymorphic object-or-array shape as the parent; captured raw (nullable).</summary>
    public JsonElement? TieredPricing { get; set; }
}

/// <summary>An image object — featured or gallery.</summary>
public class ColumbiaImage
{
    public int Id { get; set; }
    public string Src { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public string Alt { get; set; } = string.Empty;
}

/// <summary>A simple <c>{name}</c> taxonomy entry (category, tag, or color group).</summary>
public class ColumbiaNamed
{
    public string Name { get; set; } = string.Empty;
}

/// <summary>A product attribute with its option list, e.g. Color Group → [Blue], Packaging → [Bulk, 1 lb Bags].</summary>
public class ColumbiaAttribute
{
    public string Name { get; set; } = string.Empty;
    public List<ColumbiaNamed> Options { get; set; } = new();
}

/// <summary>A resolved attribute value on a specific variation, e.g. Packaging → "Bulk".</summary>
public class ColumbiaAttributeValue
{
    public string Name { get; set; } = string.Empty;
    public string Value { get; set; } = string.Empty;
}
