import { ApiProperty } from '@nestjs/swagger';
import type { Good as PrismaGood } from '@prisma/client';

export interface GoodRelations {
  country?: { id: bigint; countryName: string; countryIcon: string | null } | null;
  category?: { id: bigint; categoryName: string; categoryIcon: string | null } | null;
  tag?: { id: bigint; tagName: string; tagColor: string | null; tagFontColor: string | null } | null;
  position?: { id: bigint; indexVal: number } | null;
  originGood?: {
    id: bigint;
    sdsGoodId: string;
    source: 'SDS' | 'CUSTOM';
    goodName: string | null;
    goodImage: string | null;
    goodPrice: unknown;
    detail?: {
      productCode: string | null;
      syncedAt: Date;
      sizeChart: unknown;
      packageSpecs: unknown;
      [key: string]: unknown;
    } | null;
    variants?: Array<{
      sdsVariantId: string;
      sku: string;
      sizeName: string | null;
      colorName: string | null;
      colorHex: string | null;
      price: unknown;
      enabled: boolean;
      [key: string]: unknown;
    }>;
    _count?: { variants: number };
  } | null;
  goodTags?: { tag: { id: bigint; tagName: string; tagColor: string | null; tagFontColor: string | null } }[];
}

export class GoodDto {
  @ApiProperty()
  id!: string;

  @ApiProperty()
  goodName!: string;

  @ApiProperty({ nullable: true })
  goodImage!: string | null;

  @ApiProperty()
  goodPriority!: number;

  @ApiProperty()
  countryId!: string;

  @ApiProperty()
  categoryId!: string;

  @ApiProperty({ nullable: true })
  tagId!: string | null;

  @ApiProperty({ nullable: true })
  positionId!: string | null;

  @ApiProperty()
  originGoodId!: string;

  @ApiProperty()
  createdAt!: string;

  @ApiProperty()
  updatedAt!: string;

  @ApiProperty({ required: false, nullable: true })
  country?: { id: string; countryName: string; countryIcon: string | null } | null;

  @ApiProperty({ required: false, nullable: true })
  category?: { id: string; categoryName: string; categoryIcon: string | null } | null;

  @ApiProperty({ required: false, nullable: true })
  tag?: { id: string; tagName: string; tagColor: string | null; tagFontColor: string | null } | null;

  @ApiProperty({ required: false, type: Array })
  tags!: Array<{ id: string; tagName: string; tagColor: string | null; tagFontColor: string | null }>;

  @ApiProperty({ required: false, nullable: true })
  position?: { id: string; indexVal: number } | null;

  @ApiProperty({ required: false, nullable: true })
  originGood?: {
    id: string;
    sdsGoodId: string;
    source: 'SDS' | 'CUSTOM';
    isCustom: boolean;
    goodName: string | null;
    goodImage: string | null;
    goodPrice: string | null;
    hasDetail: boolean;
    detailSyncedAt: string | null;
    variantCount: number;
    sizeRowCount: number;
    packageRowCount: number;
    productCode: string | null;
  } | null;

  static from(
    good: PrismaGood,
    rel: GoodRelations = {},
  ): GoodDto {
    return {
      id: good.id.toString(),
      goodName: good.goodName,
      goodImage: good.goodImage,
      goodPriority: good.goodPriority,
      countryId: good.countryId.toString(),
      categoryId: good.categoryId.toString(),
      tagId: good.tagId === null || good.tagId === undefined ? null : good.tagId.toString(),
      positionId: good.positionId === null || good.positionId === undefined ? null : good.positionId.toString(),
      originGoodId: good.originGoodId.toString(),
      createdAt: good.createdAt.toISOString(),
      updatedAt: good.updatedAt.toISOString(),
      country: rel.country
        ? {
            id: rel.country.id.toString(),
            countryName: rel.country.countryName,
            countryIcon: rel.country.countryIcon,
          }
        : null,
      category: rel.category
        ? {
            id: rel.category.id.toString(),
            categoryName: rel.category.categoryName,
            categoryIcon: rel.category.categoryIcon,
          }
        : null,
      tag: rel.tag
        ? {
            id: rel.tag.id.toString(),
            tagName: rel.tag.tagName,
            tagColor: rel.tag.tagColor,
            tagFontColor: rel.tag.tagFontColor,
          }
        : null,
      tags: rel.goodTags
        ? rel.goodTags.map((gt) => ({
            id: gt.tag.id.toString(),
            tagName: gt.tag.tagName,
            tagColor: gt.tag.tagColor,
            tagFontColor: gt.tag.tagFontColor,
          }))
        : [],
      position: rel.position
        ? {
            id: rel.position.id.toString(),
            indexVal: rel.position.indexVal,
          }
        : null,
      originGood: rel.originGood
        ? {
            id: rel.originGood.id.toString(),
            sdsGoodId: rel.originGood.sdsGoodId,
            source: rel.originGood.source,
            isCustom: rel.originGood.source === 'CUSTOM',
            goodName: rel.originGood.goodName,
            goodImage: rel.originGood.goodImage,
            goodPrice:
              rel.originGood.goodPrice === null ||
              rel.originGood.goodPrice === undefined
                ? null
                : (rel.originGood.goodPrice as { toString(): string }).toString(),
            hasDetail: Boolean(rel.originGood.detail),
            detailSyncedAt: rel.originGood.detail?.syncedAt.toISOString() ?? null,
            variantCount: rel.originGood._count?.variants ?? rel.originGood.variants?.length ?? 0,
            sizeRowCount: GoodDto.jsonRows(rel.originGood.detail?.sizeChart),
            packageRowCount: GoodDto.jsonRows(rel.originGood.detail?.packageSpecs),
            productCode: rel.originGood.detail?.productCode ?? null,
          }
        : null,
    };
  }

  private static jsonRows(value: unknown): number {
    if (!value || typeof value !== 'object' || !('rows' in value)) return 0;
    const rows = (value as { rows?: unknown }).rows;
    return Array.isArray(rows) ? rows.length : 0;
  }
}

export class GoodDetailDto extends GoodDto {
  @ApiProperty({ nullable: true, type: Object })
  originDetail!: Record<string, unknown> | null;

  @ApiProperty({ type: Array })
  variants!: Array<Record<string, unknown>>;

  static fromGood(good: PrismaGood, rel: GoodRelations): GoodDetailDto {
    const base = GoodDto.from(good, rel);
    const detail = rel.originGood?.detail;
    return {
      ...base,
      originDetail: detail ? { ...detail, syncedAt: detail.syncedAt.toISOString() } : null,
      variants: (rel.originGood?.variants ?? []).map((variant) => ({
        ...variant,
        price:
          variant.price === null || variant.price === undefined
            ? null
            : (variant.price as { toString(): string }).toString(),
      })),
    };
  }
}

export interface PaginatedGoods {
  items: GoodDto[];
  total: number;
  page: number;
  pageSize: number;
}
