import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
import { useQuery } from "@tanstack/react-query";
import { z } from "zod";
import { zodValidator } from "@tanstack/zod-adapter";
import {
  ArrowLeft,
  ArrowRight,
  Loader2,
  AlertTriangle,
  Sparkles,
  Globe,
  Hash,
  Star,
  Target,
} from "lucide-react";
import { AppShell } from "@/components/AppShell";
import { PortfolioPrompt } from "@/components/PortfolioPrompt";
import { PageHeader } from "@/components/PageHeader";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Sources } from "@/components/Sources";
import { useBriefing } from "@/hooks/useBriefing";
import { supabase } from "@/integrations/supabase/client";
import type {
  SelfExam,
  SocialProfile,
  OtaListing,
} from "@/lib/selfExamination.functions";

const sectionEnum = z.enum(["health", "fix", "social", "ota", "seo", "reviews", "branding"]);
const searchSchema = z.object({ section: sectionEnum });

export const Route = createFileRoute("/self-exam-detail")({
  validateSearch: zodValidator(searchSchema),
  head: () => ({
    meta: [
      { title: "Self-Exam Detail — The Daily Ledger" },
      {
        name: "description",
        content: "Deep details, evidence and source citations for your hotel's digital presence audit.",
      },
    ],
  }),
  component: SelfExamDetailPage,
});

const SECTION_TITLES: Record<z.infer<typeof sectionEnum>, { eyebrow: string; title: string; subtitle: string }> = {
  health: {
    eyebrow: "Digital health score",
    title: "Your overall digital health",
    subtitle: "How visible, credible, and consistent your hotel looks online — across every channel travellers use.",
  },
  fix: {
    eyebrow: "What to fix",
    title: "Prioritised fixes with evidence",
    subtitle: "Each finding is grounded in 1–3 cited public sources so you can verify before acting.",
  },
  social: {
    eyebrow: "Social presence",
    title: "Your social footprint, channel by channel",
    subtitle: "Activity, follower signals and gaps across the platforms travellers actually use to discover hotels.",
  },
  ota: {
    eyebrow: "OTA presence",
    title: "Your OTA listings & ratings",
    subtitle: "Where you're bookable, what guests are scoring you, and what's missing.",
  },
  seo: {
    eyebrow: "Website & SEO",
    title: "How your website performs in search",
    subtitle: "Site fundamentals, keyword visibility and search ranking signals.",
  },
  reviews: {
    eyebrow: "Reviews",
    title: "What guests are saying",
    subtitle: "Aggregated sentiment, recurring praise and complaints.",
  },
  branding: {
    eyebrow: "Branding",
    title: "Brand clarity & visual consistency",
    subtitle: "How clearly your positioning lands online.",
  },
};

type DbRow = {
  website_url: string | null;
  social_profiles: SocialProfile[] | null;
  ota_listings: OtaListing[] | null;
  seo_data: SelfExam["seo_data"] | null;
  reviews: SelfExam["reviews"] | null;
  branding: SelfExam["branding"] | null;
  suggestions: SelfExam["suggestions"] | null;
  sources: SelfExam["sources"] | null;
  last_scanned_at: string | null;
};

function SelfExamDetailPage() {
  const { section } = Route.useSearch();
  const { hotel, isAllHotels, isHotelLoading } = useBriefing();
  const navigate = useNavigate();

  const rowQuery = useQuery({
    queryKey: ["self-exam", hotel?.id],
    enabled: !!hotel?.id,
    queryFn: async () => {
      const { data, error } = await supabase
        .from("self_examinations")
        .select("*")
        .eq("hotel_id", hotel!.id)
        .maybeSingle();
      if (error) throw error;
      return (data as DbRow | null) ?? null;
    },
  });

  if (isHotelLoading) {
    return (
      <div className="flex min-h-dvh items-center justify-center">
        <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
      </div>
    );
  }
  if (isAllHotels || !hotel) return <PortfolioPrompt pageTitle="Self-Exam" />;

  const r = rowQuery.data;
  const hasAudit = !!(r && r.seo_data && r.last_scanned_at);
  const meta = SECTION_TITLES[section as z.infer<typeof sectionEnum>];

  return (
    <AppShell hotel={hotel} isLoading={rowQuery.isLoading} onRefresh={() => rowQuery.refetch()}>
      <div className="mb-4">
        <Button
          variant="ghost"
          size="sm"
          onClick={() => navigate({ to: "/self-examination" })}
          className="gap-1.5 text-muted-foreground"
        >
          <ArrowLeft className="h-3.5 w-3.5" /> Back to Self-Exam
        </Button>
      </div>

      <PageHeader eyebrow={meta.eyebrow} title={meta.title} subtitle={meta.subtitle} />

      {rowQuery.isLoading ? (
        <div className="flex items-center justify-center py-12">
          <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
        </div>
      ) : !hasAudit ? (
        <div className="rounded-2xl border-2 border-dashed bg-card/50 p-10 text-center">
          <p className="font-serif text-lg text-foreground">No audit yet</p>
          <p className="mt-1 text-sm text-muted-foreground">
            Run an audit on the Self-Exam page to see full details here.
          </p>
          <Button asChild className="mt-4">
            <Link to="/self-examination">Go to Self-Exam</Link>
          </Button>
        </div>
      ) : (
        <SectionDetail section={section} row={r!} currency={hotel.currency || "MYR"} />
      )}

      {hasAudit ? <ActionsCta /> : null}
    </AppShell>
  );
}

function ActionsCta() {
  return (
    <article className="mt-10 rounded-2xl border border-brand/30 bg-gradient-to-br from-brand-soft/40 to-card p-6 shadow-[var(--shadow-elegant)]">
      <div className="flex flex-wrap items-center justify-between gap-4">
        <div>
          <div className="mb-1 inline-flex items-center gap-1.5 text-xs uppercase tracking-[0.18em] text-brand">
            <Target className="h-3.5 w-3.5" /> Turn findings into moves
          </div>
          <h3 className="font-serif text-xl text-foreground">Ready to act on these gaps?</h3>
          <p className="mt-1 text-sm text-muted-foreground">
            See the three concrete moves we recommend today — based on your audit and current market signals.
          </p>
        </div>
        <Button asChild className="gap-2">
          <Link to="/actions">
            View suggested actions <ArrowRight className="h-4 w-4" />
          </Link>
        </Button>
      </div>
    </article>
  );
}

function SectionDetail({
  section,
  row,
  currency,
}: {
  section: z.infer<typeof sectionEnum>;
  row: DbRow;
  currency: string;
}) {
  const audit: SelfExam = {
    website_url: row.website_url ?? null,
    seo_data: row.seo_data!,
    ota_listings: row.ota_listings ?? [],
    social_profiles: row.social_profiles ?? [],
    reviews: row.reviews ?? {},
    branding: row.branding ?? { brand_clarity: "okay", visual_consistency: "unknown" },
    suggestions: row.suggestions ?? [],
    sources: row.sources ?? [],
    health_score: (row.seo_data as unknown as { health_score?: number })?.health_score ?? 0,
  } as unknown as SelfExam;

  switch (section) {
    case "health":
      return <HealthDetail audit={audit} />;
    case "fix":
      return <FixDetail audit={audit} />;
    case "social":
      return <SocialDetail audit={audit} />;
    case "ota":
      return <OtaDetail audit={audit} currency={currency} />;
    case "seo":
      return <SeoDetail audit={audit} />;
    case "reviews":
      return <ReviewsDetail audit={audit} />;
    case "branding":
      return <BrandingDetail audit={audit} />;
  }
}

function HealthDetail({ audit }: { audit: SelfExam }) {
  const score = Math.round(audit.health_score ?? 0);
  const scoreColor =
    score >= 75 ? "text-emerald-600" : score >= 50 ? "text-amber-600" : "text-destructive";
  const verdict =
    score >= 75
      ? "Strong digital footprint. Focus on polish and incremental gains."
      : score >= 50
        ? "Decent foundation, with meaningful gaps to close."
        : "Critical gaps — guests likely struggle to find or trust you online.";

  const breakdown = [
    { label: "Website / SEO", value: audit.seo_data.has_official_website ? 75 : 25 },
    { label: "OTA presence", value: Math.min(100, audit.ota_listings.length * 20) },
    {
      label: "Social activity",
      value: Math.min(
        100,
        audit.social_profiles.filter((s) => s.activity === "active").length * 20,
      ),
    },
    {
      label: "Reviews",
      value: audit.reviews.avg_rating ? Math.round((audit.reviews.avg_rating / 10) * 100) : 0,
    },
    {
      label: "Branding",
      value:
        audit.branding.brand_clarity === "strong"
          ? 90
          : audit.branding.brand_clarity === "okay"
            ? 60
            : 30,
    },
  ];

  return (
    <div className="space-y-6">
      <article className="rounded-2xl border bg-gradient-to-br from-brand-soft/40 to-card p-6 shadow-[var(--shadow-elegant)] sm:p-8">
        <div className="flex flex-wrap items-end justify-between gap-4">
          <div>
            <div className="text-xs uppercase tracking-[0.18em] text-muted-foreground">
              Digital health score
            </div>
            <div className={`font-serif text-6xl font-medium ${scoreColor}`}>{score}</div>
            <div className="text-xs text-muted-foreground">out of 100</div>
          </div>
          {audit.website_url ? (
            <a
              href={audit.website_url}
              target="_blank"
              rel="noopener noreferrer"
              className="inline-flex items-center gap-1.5 text-sm text-brand hover:underline"
            >
              <Globe className="h-3.5 w-3.5" /> {audit.website_url}
            </a>
          ) : null}
        </div>
        <p className="mt-4 font-serif text-base italic text-muted-foreground">{verdict}</p>
      </article>

      <article className="rounded-2xl border bg-card p-6 shadow-sm">
        <h3 className="mb-4 font-serif text-lg text-brand">Score breakdown</h3>
        <div className="space-y-3">
          {breakdown.map((b) => (
            <div key={b.label}>
              <div className="mb-1 flex items-center justify-between text-xs">
                <span className="text-muted-foreground">{b.label}</span>
                <span className="text-foreground">{b.value}</span>
              </div>
              <div className="h-2 w-full overflow-hidden rounded-full bg-muted">
                <div
                  className="h-full rounded-full bg-brand"
                  style={{ width: `${b.value}%` }}
                />
              </div>
            </div>
          ))}
        </div>
      </article>

      <article className="rounded-2xl border bg-card p-6 shadow-sm">
        <h3 className="mb-3 font-serif text-lg text-brand">Evidence & sources</h3>
        <p className="mb-2 text-xs text-muted-foreground">
          Every claim is grounded in cross-validated public sources. Click each to verify.
        </p>
        <Sources items={audit.sources} label="All sources" />
      </article>
    </div>
  );
}

function FixDetail({ audit }: { audit: SelfExam }) {
  if (audit.suggestions.length === 0) {
    return (
      <p className="text-sm italic text-muted-foreground">
        No issues detected — well done. Re-scan periodically to stay sharp.
      </p>
    );
  }
  return (
    <div className="space-y-4">
      {audit.suggestions.map((s, i) => {
        const sevColor =
          s.severity === "critical"
            ? "border-destructive/40 bg-destructive/5"
            : s.severity === "improve"
              ? "border-amber-300/40 bg-amber-50/40"
              : "border-border bg-card";
        const sevIcon =
          s.severity === "critical" ? (
            <AlertTriangle className="h-4 w-4 text-destructive" />
          ) : (
            <Sparkles className="h-4 w-4 text-amber-600" />
          );
        return (
          <article key={i} className={`rounded-2xl border p-5 ${sevColor}`}>
            <div className="mb-2 flex flex-wrap items-center gap-2">
              {sevIcon}
              <Badge variant="secondary" className="text-[10px] uppercase">
                {s.area}
              </Badge>
              <Badge variant="outline" className="text-[10px] uppercase">
                {s.severity}
              </Badge>
            </div>
            <p className="font-serif text-base text-foreground">{s.finding}</p>
            <p className="mt-2 text-sm text-muted-foreground">
              <strong className="text-foreground">Do this: </strong>
              {s.recommendation}
            </p>
            <div className="mt-3 rounded-lg border bg-background/60 p-3">
              <div className="mb-1 text-[10px] uppercase tracking-wider text-muted-foreground">
                Cross-validated evidence ({s.sources.length} {s.sources.length === 1 ? "source" : "sources"})
              </div>
              <Sources items={s.sources} label="View sources" />
            </div>
          </article>
        );
      })}
    </div>
  );
}

function SocialDetail({ audit }: { audit: SelfExam }) {
  return (
    <div className="grid gap-4 sm:grid-cols-2">
      {audit.social_profiles.map((s, i) => (
        <article key={i} className="rounded-2xl border bg-card p-5 shadow-sm">
          <div className="flex items-center justify-between">
            <div className="font-serif text-lg capitalize text-foreground">{s.platform}</div>
            <ActivityBadge activity={s.activity} />
          </div>
          {s.url || s.handle ? (
            <a
              href={s.url ?? "#"}
              target="_blank"
              rel="noopener noreferrer"
              className="mt-2 block truncate text-sm text-brand hover:underline"
            >
              {s.handle ?? s.url}
            </a>
          ) : (
            <div className="mt-2 text-sm italic text-muted-foreground">Not detected</div>
          )}
          <div className="mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground">
            {s.followers != null ? (
              <span>
                <strong className="text-foreground">{s.followers.toLocaleString()}</strong> followers
              </span>
            ) : null}
            {s.last_post ? (
              <span>
                Last post: <strong className="text-foreground">{s.last_post}</strong>
              </span>
            ) : null}
          </div>
          {s.notes ? <p className="mt-3 text-sm text-muted-foreground">{s.notes}</p> : null}
        </article>
      ))}
      <article className="rounded-2xl border bg-card p-5 shadow-sm sm:col-span-2">
        <h3 className="mb-2 font-serif text-base text-brand">Sources</h3>
        <Sources items={audit.sources} label="Evidence" />
      </article>
    </div>
  );
}

function OtaDetail({ audit, currency }: { audit: SelfExam; currency: string }) {
  if (audit.ota_listings.length === 0) {
    return <p className="text-sm italic text-muted-foreground">No OTA listings detected.</p>;
  }
  return (
    <div className="space-y-4">
      <div className="grid gap-4 sm:grid-cols-2">
        {audit.ota_listings.map((o, i) => (
          <article key={i} className="rounded-2xl border bg-card p-5 shadow-sm">
            <div className="flex items-center justify-between">
              <div className="font-serif text-lg text-foreground">{o.channel}</div>
              {o.rating != null ? (
                <div className="inline-flex items-center gap-1 text-sm text-amber-600">
                  <Star className="h-4 w-4 fill-current" /> {o.rating.toFixed(1)}
                  {o.reviews ? (
                    <span className="text-xs text-muted-foreground">({o.reviews})</span>
                  ) : null}
                </div>
              ) : null}
            </div>
            {o.url ? (
              <a
                href={o.url}
                target="_blank"
                rel="noopener noreferrer"
                className="mt-2 block truncate text-sm text-brand hover:underline"
              >
                {o.url}
              </a>
            ) : null}
            {o.starting_price != null ? (
              <div className="mt-2 text-sm text-muted-foreground">
                From{" "}
                <strong className="text-foreground">
                  {o.currency || currency} {o.starting_price}
                </strong>
              </div>
            ) : null}
            {o.notes ? <p className="mt-2 text-sm text-muted-foreground">{o.notes}</p> : null}
          </article>
        ))}
      </div>
      <article className="rounded-2xl border bg-card p-5 shadow-sm">
        <h3 className="mb-2 font-serif text-base text-brand">Sources</h3>
        <Sources items={audit.sources} label="Evidence" />
      </article>
    </div>
  );
}

function SeoDetail({ audit }: { audit: SelfExam }) {
  return (
    <article className="rounded-2xl border bg-card p-6 shadow-sm">
      <div className="grid gap-3 sm:grid-cols-2">
        <KV label="Official website" value={audit.seo_data.has_official_website ? "Yes" : "No"} />
        <KV label="HTTPS" value={fmtBool(audit.seo_data.has_https)} />
        <KV label="Mobile friendly" value={fmtBool(audit.seo_data.mobile_friendly)} />
        <KV label="Booking engine" value={fmtBool(audit.seo_data.has_booking_engine)} />
        {audit.seo_data.estimated_search_ranking ? (
          <KV
            label="Search ranking"
            value={audit.seo_data.estimated_search_ranking}
            className="sm:col-span-2"
          />
        ) : null}
      </div>
      {audit.seo_data.meta_title ? (
        <div className="mt-4 rounded-md border bg-background p-3 text-sm">
          <div className="text-[10px] uppercase tracking-wider text-muted-foreground">Meta title</div>
          <div className="text-foreground">{audit.seo_data.meta_title}</div>
          {audit.seo_data.meta_description ? (
            <p className="mt-1 text-xs text-muted-foreground">{audit.seo_data.meta_description}</p>
          ) : null}
        </div>
      ) : null}

      {(audit.seo_data.ranked_keywords?.length ?? 0) > 0 ? (
        <div className="mt-4">
          <div className="mb-1 inline-flex items-center gap-1 text-[10px] uppercase tracking-wider text-emerald-700">
            <Hash className="h-3 w-3" /> Ranking for
          </div>
          <div className="flex flex-wrap gap-1.5">
            {audit.seo_data.ranked_keywords.map((k, i) => (
              <Badge key={i} variant="secondary" className="text-[11px]">
                {k}
              </Badge>
            ))}
          </div>
        </div>
      ) : null}

      {(audit.seo_data.missing_keywords?.length ?? 0) > 0 ? (
        <div className="mt-4">
          <div className="mb-1 inline-flex items-center gap-1 text-[10px] uppercase tracking-wider text-destructive">
            <Hash className="h-3 w-3" /> Missing keywords
          </div>
          <div className="flex flex-wrap gap-1.5">
            {audit.seo_data.missing_keywords.map((k, i) => (
              <Badge key={i} variant="outline" className="text-[11px]">
                {k}
              </Badge>
            ))}
          </div>
        </div>
      ) : null}

      {audit.seo_data.performance_notes ? (
        <p className="mt-3 text-sm text-muted-foreground">{audit.seo_data.performance_notes}</p>
      ) : null}

      <div className="mt-5 border-t pt-4">
        <Sources items={audit.sources} label="Evidence" />
      </div>
    </article>
  );
}

function ReviewsDetail({ audit }: { audit: SelfExam }) {
  return (
    <article className="rounded-2xl border bg-card p-6 shadow-sm">
      {audit.reviews.avg_rating != null ? (
        <div className="font-serif text-4xl font-medium text-foreground">
          {audit.reviews.avg_rating.toFixed(1)}
          {audit.reviews.total_reviews ? (
            <span className="ml-2 text-sm text-muted-foreground">
              ({audit.reviews.total_reviews} reviews)
            </span>
          ) : null}
        </div>
      ) : (
        <p className="text-sm italic text-muted-foreground">No aggregated rating detected.</p>
      )}
      {audit.reviews.best_quote ? (
        <p className="mt-4 border-l-2 border-emerald-400 pl-3 text-sm italic text-foreground">
          "{audit.reviews.best_quote}"
        </p>
      ) : null}
      {audit.reviews.worst_quote ? (
        <p className="mt-2 border-l-2 border-destructive/60 pl-3 text-sm italic text-muted-foreground">
          "{audit.reviews.worst_quote}"
        </p>
      ) : null}
      {audit.reviews.common_praise?.length ? (
        <div className="mt-4">
          <div className="text-[10px] uppercase tracking-wider text-emerald-700">Common praise</div>
          <ul className="mt-1 list-disc pl-5 text-sm text-muted-foreground">
            {audit.reviews.common_praise.map((c, i) => (
              <li key={i}>{c}</li>
            ))}
          </ul>
        </div>
      ) : null}
      {audit.reviews.common_complaints?.length ? (
        <div className="mt-4">
          <div className="text-[10px] uppercase tracking-wider text-destructive">Recurring complaints</div>
          <ul className="mt-1 list-disc pl-5 text-sm text-muted-foreground">
            {audit.reviews.common_complaints.map((c, i) => (
              <li key={i}>{c}</li>
            ))}
          </ul>
        </div>
      ) : null}
      <div className="mt-5 border-t pt-4">
        <Sources items={audit.sources} label="Evidence" />
      </div>
    </article>
  );
}

function BrandingDetail({ audit }: { audit: SelfExam }) {
  return (
    <article className="rounded-2xl border bg-card p-6 shadow-sm">
      <div className="flex flex-wrap gap-2">
        <Badge variant="secondary" className="capitalize">
          Clarity: {audit.branding.brand_clarity}
        </Badge>
        <Badge variant="outline" className="capitalize">
          Visuals: {audit.branding.visual_consistency}
        </Badge>
      </div>
      {audit.branding.tagline ? (
        <p className="mt-4 font-serif text-lg italic text-foreground">"{audit.branding.tagline}"</p>
      ) : null}
      {audit.branding.notes ? (
        <p className="mt-3 text-sm text-muted-foreground">{audit.branding.notes}</p>
      ) : null}
      <div className="mt-5 border-t pt-4">
        <Sources items={audit.sources} label="Evidence" />
      </div>
    </article>
  );
}

function ActivityBadge({ activity }: { activity: SocialProfile["activity"] }) {
  const map: Record<SocialProfile["activity"], string> = {
    active: "bg-emerald-100 text-emerald-800",
    stale: "bg-amber-100 text-amber-800",
    inactive: "bg-zinc-100 text-zinc-700",
    missing: "bg-destructive/10 text-destructive",
  };
  return (
    <span className={`rounded-full px-2 py-0.5 text-[10px] font-medium uppercase ${map[activity]}`}>
      {activity}
    </span>
  );
}

function KV({ label, value, className = "" }: { label: string; value: string; className?: string }) {
  return (
    <div className={className}>
      <div className="text-[10px] uppercase tracking-wider text-muted-foreground">{label}</div>
      <div className="text-sm text-foreground">{value}</div>
    </div>
  );
}

function fmtBool(v?: boolean | null) {
  if (v === true) return "Yes";
  if (v === false) return "No";
  return "Unknown";
}
