import type {
  Category,
  PortfolioAsset,
  PortfolioProject,
  PortfolioProjectViewMode,
  PortfolioSection,
} from "@prisma/client";

import { getPortfolioMediaBindings } from "@/lib/media";
import type { AppLocale } from "@/lib/locale";
import { prisma } from "@/lib/prisma";

type CategoryRecord = Pick<
  Category,
  | "id"
  | "slug"
  | "nameAr"
  | "nameEn"
  | "nameDe"
  | "descriptionAr"
  | "descriptionEn"
  | "descriptionDe"
  | "sortOrder"
  | "isActive"
>;

type SectionRecord = Pick<
  PortfolioSection,
  | "id"
  | "type"
  | "titleAr"
  | "titleEn"
  | "titleDe"
  | "bodyAr"
  | "bodyEn"
  | "bodyDe"
  | "imagePath"
  | "linkUrl"
  | "sortOrder"
>;

type AssetRecord = Pick<
  PortfolioAsset,
  "id" | "kind" | "filePath" | "altAr" | "altEn" | "altDe" | "sortOrder"
>;

type ProjectRecord = Pick<
  PortfolioProject,
  | "id"
  | "slug"
  | "viewMode"
  | "titleAr"
  | "titleEn"
  | "titleDe"
  | "summaryAr"
  | "summaryEn"
  | "summaryDe"
  | "clientName"
  | "projectYear"
  | "serviceLabelAr"
  | "serviceLabelEn"
  | "serviceLabelDe"
  | "previewUrl"
  | "coverImagePath"
  | "isFeatured"
  | "isPublished"
  | "publishedAt"
  | "sortOrder"
>;

export type LocalizedContent = {
  ar: string;
  en: string;
  de: string;
};

export type PortfolioCategoryView = {
  id: string;
  slug: string;
  name: LocalizedContent;
  description: LocalizedContent;
  sortOrder: number;
  isActive: boolean;
};

export type PortfolioSectionView = {
  id: string;
  type: SectionRecord["type"];
  title: LocalizedContent;
  body: LocalizedContent;
  imagePath: string | null;
  mediaAssetId: string | null;
  linkUrl: string | null;
  sortOrder: number;
};

export type PortfolioAssetView = {
  id: string;
  kind: AssetRecord["kind"];
  filePath: string;
  mediaAssetId: string | null;
  alt: LocalizedContent;
  sortOrder: number;
};

export type PortfolioProjectView = {
  id: string;
  slug: string;
  viewMode: PortfolioProjectViewMode;
  title: LocalizedContent;
  summary: LocalizedContent;
  clientName: string;
  projectYear: number;
  serviceLabel: LocalizedContent;
  previewUrl: string | null;
  coverImagePath: string | null;
  coverMediaAssetId: string | null;
  isFeatured: boolean;
  isPublished: boolean;
  publishedAt: Date | null;
  sortOrder: number;
  category: PortfolioCategoryView;
  sections: PortfolioSectionView[];
  assets: PortfolioAssetView[];
};

export function resolvePortfolioProjectViewMode(
  value: string | null | undefined,
): PortfolioProjectViewMode {
  switch (value) {
    case "STORY":
      return "STORY";
    case "CASE_STUDY":
      return "CASE_STUDY";
    case "GRID":
    default:
      return "GRID";
  }
}

function mapLocalizedContent(record: Record<string, unknown>, prefix: string): LocalizedContent {
  return {
    ar: String(record[`${prefix}Ar`] ?? ""),
    en: String(record[`${prefix}En`] ?? ""),
    de: String(record[`${prefix}De`] ?? ""),
  };
}

function mapCategory(record: CategoryRecord): PortfolioCategoryView {
  return {
    id: record.id,
    slug: record.slug,
    name: mapLocalizedContent(record, "name"),
    description: mapLocalizedContent(record, "description"),
    sortOrder: record.sortOrder,
    isActive: record.isActive,
  };
}

function mapSection(record: SectionRecord, mediaAssetId: string | null): PortfolioSectionView {
  return {
    id: record.id,
    type: record.type,
    title: mapLocalizedContent(record, "title"),
    body: mapLocalizedContent(record, "body"),
    imagePath: record.imagePath,
    mediaAssetId,
    linkUrl: record.linkUrl,
    sortOrder: record.sortOrder,
  };
}

function mapAsset(record: AssetRecord, mediaAssetId: string | null): PortfolioAssetView {
  return {
    id: record.id,
    kind: record.kind,
    filePath: record.filePath,
    mediaAssetId,
    alt: mapLocalizedContent(record, "alt"),
    sortOrder: record.sortOrder,
  };
}

function mapProject(
  record: ProjectRecord & {
    category: CategoryRecord;
    sections: SectionRecord[];
    assets: AssetRecord[];
  },
  mediaBindings?: {
    coverAssetId: string | null;
    sectionAssetIds: Record<string, string>;
    assetIds: Record<string, string>;
  },
): PortfolioProjectView {
  return {
    id: record.id,
    slug: record.slug,
    viewMode: resolvePortfolioProjectViewMode(record.viewMode),
    title: mapLocalizedContent(record, "title"),
    summary: mapLocalizedContent(record, "summary"),
    clientName: record.clientName,
    projectYear: record.projectYear,
    serviceLabel: mapLocalizedContent(record, "serviceLabel"),
    previewUrl: record.previewUrl,
    coverImagePath: record.coverImagePath,
    coverMediaAssetId: mediaBindings?.coverAssetId ?? null,
    isFeatured: record.isFeatured,
    isPublished: record.isPublished,
    publishedAt: record.publishedAt,
    sortOrder: record.sortOrder,
    category: mapCategory(record.category),
    sections: record.sections.map((section) =>
      mapSection(section, mediaBindings?.sectionAssetIds[section.id] ?? null),
    ),
    assets: record.assets.map((asset) => mapAsset(asset, mediaBindings?.assetIds[asset.id] ?? null)),
  };
}

export function getLocalizedValue(
  content: LocalizedContent,
  locale: AppLocale,
  fallbackLocale: AppLocale = "de",
): string {
  const direct = content[locale]?.trim();

  if (direct) {
    return direct;
  }

  const fallback = content[fallbackLocale]?.trim();

  if (fallback) {
    return fallback;
  }

  return content.ar || content.en || content.de || "";
}

export async function getAdminPortfolioCategories() {
  const categories = await prisma.category.findMany({
    include: {
      _count: {
        select: {
          projects: true,
        },
      },
    },
    orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
  });

  return categories.map((category) => ({
    ...mapCategory(category),
    projectCount: category._count.projects,
  }));
}

export async function getActivePortfolioCategories() {
  const categories = await prisma.category.findMany({
    where: {
      isActive: true,
    },
    orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
  });

  return categories.map(mapCategory);
}

export async function getActivePortfolioCategoryBySlug(slug: string) {
  const category = await prisma.category.findFirst({
    where: {
      slug,
      isActive: true,
    },
  });

  return category ? mapCategory(category) : null;
}

export async function getAdminPortfolioProjects(filters?: {
  categoryId?: string;
  status?: "all" | "draft" | "published";
}) {
  const projects = await prisma.portfolioProject.findMany({
    where: {
      ...(filters?.categoryId ? { categoryId: filters.categoryId } : {}),
      ...(filters?.status === "draft"
        ? { isPublished: false }
        : filters?.status === "published"
          ? { isPublished: true }
          : {}),
    },
    include: {
      category: true,
      sections: {
        orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
      },
      assets: {
        orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
      },
    },
    orderBy: [{ sortOrder: "asc" }, { createdAt: "desc" }],
  });

  return projects.map((project) => mapProject(project));
}

export async function getPublishedPortfolioProjects(filters?: { categorySlug?: string }) {
  const projects = await prisma.portfolioProject.findMany({
    where: {
      isPublished: true,
      category: {
        isActive: true,
        ...(filters?.categorySlug ? { slug: filters.categorySlug } : {}),
      },
    },
    include: {
      category: true,
      sections: {
        orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
      },
      assets: {
        orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
      },
    },
    orderBy: [{ sortOrder: "asc" }, { publishedAt: "desc" }, { createdAt: "desc" }],
  });

  return projects.map((project) => mapProject(project));
}

export async function getPublishedPortfolioProjectBySlug(slug: string) {
  const project = await prisma.portfolioProject.findFirst({
    where: {
      slug,
      isPublished: true,
      category: {
        isActive: true,
      },
    },
    include: {
      category: true,
      sections: {
        orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
      },
      assets: {
        orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
      },
    },
  });

  return project ? mapProject(project) : null;
}

export async function getAdminPortfolioProjectById(id: string) {
  const project = await prisma.portfolioProject.findUnique({
    where: {
      id,
    },
    include: {
      category: true,
      sections: {
        orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
      },
      assets: {
        orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
      },
    },
  });

  if (!project) {
    return null;
  }

  const mediaBindings = await getPortfolioMediaBindings(project.id);

  return mapProject(project, mediaBindings);
}
