/**
 * Deterministic QA for manual and CSV content — no AI-generation rubrics.
 */

import { formatBusinessContextMarkdown } from "@/lib/context/business-context";
import { validateContentRelevance } from "@/lib/context/validators/content-relevance";
import { getQaThreshold, qaScoreToEngagement } from "@/lib/generation/generation-qa";
import type { BannerLayoutId } from "@/lib/generation/banner-layouts";
import { listVisiblePlatforms } from "@/lib/social/platforms";
import type { SocialPlatformId } from "@/lib/social/platforms";
import type {
  BrandProfile,
  ContentMediaType,
  GeneratedPost,
  GenerationQaReportSnapshot,
  PostingContextData,
} from "@/types/workflow";

const PLATFORM_CAPTION_LIMITS: Record<string, number> = {
  linkedin: 3000,
  facebook: 63206,
  instagram: 2200,
  youtube: 4900,
  threads: 500,
  pinterest: 500,
  tiktok: 2200,
};

const MANUAL_QA_LAYOUT: BannerLayoutId = "center_cta";
const MANUAL_QA_MEDIA_ID = "manual-content";

export interface ManualContentQaInput {
  caption: string;
  title?: string;
  platforms: string[];
  mediaType?: ContentMediaType;
  imageUrl?: string | null;
  videoUrl?: string | null;
  linkUrl?: string;
  companyName: string;
  allowedFacts?: string;
  businessContextConfirmed?: boolean;
}

function clamp10(n: number): number {
  return Math.max(0, Math.min(10, Math.round(n * 10) / 10));
}

function isValidHttpUrl(value: string): boolean {
  try {
    const url = new URL(value);
    return url.protocol === "http:" || url.protocol === "https:";
  } catch {
    return false;
  }
}

function scoreCaptionBasics(caption: string): { score: number; issues: string[] } {
  const issues: string[] = [];
  const trimmed = caption.trim();
  let score = 10;

  if (!trimmed) {
    return { score: 0, issues: ["Caption is required"] };
  }
  if (trimmed.length < 10) {
    issues.push("Caption is very short — add more context before publishing");
    score -= 3;
  }
  if (trimmed.length > 5000) {
    issues.push("Caption exceeds maximum length (5000 characters)");
    score = 0;
  }

  return { score: clamp10(score), issues };
}

function scorePlatformLimits(
  caption: string,
  platforms: string[],
): { score: number; issues: string[] } {
  const issues: string[] = [];
  let score = 10;

  if (!platforms.length) {
    return { score: 0, issues: ["At least one platform must be selected"] };
  }

  const knownPlatforms = new Set(listVisiblePlatforms().map((p) => p.id));
  for (const platform of platforms) {
    if (!knownPlatforms.has(platform as SocialPlatformId)) {
      issues.push(`Unknown platform: ${platform}`);
      score -= 2;
    }
    const limit = PLATFORM_CAPTION_LIMITS[platform];
    if (limit && caption.length > limit) {
      issues.push(`Caption exceeds ${platform} limit (${limit} characters)`);
      score = Math.min(score, 4);
    }
  }

  return { score: clamp10(score), issues };
}

function scoreMediaRequirements(input: ManualContentQaInput): { score: number; issues: string[] } {
  const issues: string[] = [];
  let score = 10;
  const mediaType = input.mediaType ?? "content";

  if (mediaType === "image" && !input.imageUrl?.trim()) {
    issues.push("Image URL is required when mediaType is image");
    score = 0;
  }
  if (mediaType === "video" && !input.videoUrl?.trim()) {
    issues.push("Video URL is required when mediaType is video");
    score = 0;
  }
  if (input.platforms.includes("youtube") && !input.videoUrl?.trim()) {
    issues.push("YouTube requires a video URL");
    score = Math.min(score, 3);
  }
  if (
    input.platforms.includes("instagram") &&
    mediaType === "image" &&
    !input.imageUrl?.trim()
  ) {
    issues.push("Instagram image posts require an image URL");
    score = Math.min(score, 4);
  }

  return { score: clamp10(score), issues };
}

function scoreLink(input: ManualContentQaInput): { score: number; issues: string[] } {
  const link = input.linkUrl?.trim();
  if (!link) return { score: 10, issues: [] };
  if (!isValidHttpUrl(link)) {
    return { score: 4, issues: ["Link URL must be a valid http(s) URL"] };
  }
  return { score: 10, issues: [] };
}

export function evaluateManualContentQa(input: ManualContentQaInput): GenerationQaReportSnapshot {
  const threshold = getQaThreshold();
  const issues: string[] = [];
  const improvements: string[] = [];

  const basics = scoreCaptionBasics(input.caption);
  const platforms = scorePlatformLimits(input.caption, input.platforms);
  const media = scoreMediaRequirements(input);
  const link = scoreLink(input);

  issues.push(...basics.issues, ...platforms.issues, ...media.issues, ...link.issues);

  const relevance = validateContentRelevance(
    input.caption,
    input.companyName,
    input.allowedFacts,
  );
  if (!relevance.valid) {
    issues.push(...relevance.criticalIssues.map((i) => `Relevance: ${i}`));
    improvements.push(
      "Remove placeholder names, invented metrics, and off-brand references.",
      `Keep content aligned with ${input.companyName || "the project brand"}.`,
    );
  }
  if (relevance.warnings.length) {
    improvements.push(...relevance.warnings.slice(0, 2));
  }

  if (input.businessContextConfirmed === false) {
    improvements.push(
      "Confirm business context in Posting Context for stronger factual grounding checks.",
    );
  }

  const contentQuality = clamp10(
    (basics.score + platforms.score + link.score) / 3,
  );
  const brandAlignment = relevance.valid ? clamp10(8 + (relevance.warnings.length ? -1 : 0)) : 3;
  const bannerCompleteness =
    input.mediaType === "image" || input.imageUrl ? (input.imageUrl ? 10 : 5) : 8;
  const videoQuality =
    input.mediaType === "video" || input.videoUrl
      ? input.videoUrl
        ? 10
        : 3
      : input.platforms.includes("youtube")
        ? 2
        : 8;

  const overall = clamp10(
    contentQuality * 0.4 +
      brandAlignment * 0.25 +
      media.score * 0.2 +
      bannerCompleteness * 0.075 +
      videoQuality * 0.075,
  );

  if (contentQuality < threshold) {
    improvements.push("Expand the caption with clear, factual messaging.");
  }
  if (media.score < threshold) {
    improvements.push("Add required media for the selected platforms.");
  }

  const passed =
    overall >= threshold &&
    relevance.valid &&
    basics.score > 0 &&
    platforms.score > 0 &&
    media.score > 0;

  return {
    scores: {
      contentQuality,
      humanLikeness: contentQuality,
      brandAlignment,
      bannerCompleteness,
      videoQuality,
      overall,
    },
    passed,
    threshold,
    layoutId: MANUAL_QA_LAYOUT,
    layoutSeed: 0,
    mediaAssetId: MANUAL_QA_MEDIA_ID,
    issues: [...new Set(issues)],
    improvements: [...new Set(improvements)].slice(0, 8),
    attempts: 1,
    captionRetried: false,
  };
}

export function attachManualContentQa(
  post: GeneratedPost,
  brand: BrandProfile,
  context?: PostingContextData,
): GeneratedPost {
  const companyName = brand.companyName?.trim() || post.projectName;
  const allowedFacts = context?.businessContext?.confirmed
    ? formatBusinessContextMarkdown(context.businessContext)
    : undefined;

  const report = evaluateManualContentQa({
    caption: post.caption,
    title: post.title,
    platforms: post.platforms,
    mediaType: post.mediaType,
    imageUrl: post.imageUrl,
    videoUrl: post.videoUrl,
    linkUrl: post.linkUrl,
    companyName,
    allowedFacts,
    businessContextConfirmed: context?.businessContext?.confirmed,
  });

  return {
    ...post,
    qualityReport: report,
    engagementScore: qaScoreToEngagement(report.scores.overall),
  };
}
