"use client";

import { useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { useLocalStorage } from "@/lib/hooks/use-local-storage";
import { SEED_FILINGS } from "@/lib/sag/filings-seed";
import { KNOWN_LICENSES } from "@/lib/sag/licenses-seed";
import { DOMAINS } from "@/lib/sag/domains";
import { PITCHES } from "@/lib/sag/pitches";
import { ALL_ORGANIZATIONS } from "@/lib/sag/entities";
import {
  aggregateCalendarEvents,
  type CalendarEvent as AggregatedCalendarEvent,
} from "@/lib/calendar/aggregate-events";

type EventKind =
  | "filing"
  | "license"
  | "domain"
  | "raise"
  | "ttb"
  | "music-release"
  | "music-booking"
  | "social-post"
  | "mail-suggested-event";

interface CalendarEvent {
  id: string;
  date: string; // ISO yyyy-mm-dd
  title: string;
  kind: EventKind;
  entitySlug?: string;
  href: string;
}

const KIND_COLOR: Record<EventKind, string> = {
  filing: "bg-blue-500",
  license: "bg-purple-500",
  domain: "bg-amber-500",
  raise: "bg-emerald-500",
  ttb: "bg-[var(--sag-brand)]",
  "music-release": "bg-purple-500",
  "music-booking": "bg-fuchsia-500",
  "social-post": "bg-cyan-500",
  "mail-suggested-event": "bg-rose-500",
};

const KIND_LABEL: Record<EventKind, string> = {
  filing: "Filing",
  license: "License",
  domain: "Domain",
  raise: "Raise",
  ttb: "TTB",
  "music-release": "Music release",
  "music-booking": "Booking",
  "social-post": "Social post",
  "mail-suggested-event": "From email",
};

const ALL_KINDS: EventKind[] = [
  "filing",
  "license",
  "domain",
  "raise",
  "ttb",
  "music-release",
  "music-booking",
  "social-post",
  "mail-suggested-event",
];

export function ComplianceCalendar() {
  const [filingState] = useLocalStorage<Record<string, { status?: string; nextDueDate?: string }>>(
    "sag.filings.state",
    {}
  );
  const [licenseOverrides] = useLocalStorage<Record<string, { expiresDate?: string }>>(
    "sag.licenses.overrides",
    {}
  );
  const [domainOverrides] = useLocalStorage<Record<string, { expirationIso?: string }>>(
    "sag.domains.overrides",
    {}
  );

  const today = new Date();
  const [cursor, setCursor] = useState(() => new Date(today.getFullYear(), today.getMonth(), 1));
  const [kindFilters, setKindFilters] = useState<Set<EventKind>>(() => new Set(ALL_KINDS));

  // Aggregated events sourced from localStorage (music releases, music
  // bookings, scheduled social posts). Loaded post-mount + on visibility
  // change so cross-tab edits in /app/music or /app/social show up here.
  const [aggregated, setAggregated] = useState<AggregatedCalendarEvent[]>([]);
  useEffect(() => {
    const refresh = () => setAggregated(aggregateCalendarEvents(new Date()));
    refresh();
    const onVisibility = () => {
      if (document.visibilityState === "visible") refresh();
    };
    document.addEventListener("visibilitychange", onVisibility);
    return () => document.removeEventListener("visibilitychange", onVisibility);
  }, []);

  const events = useMemo(() => {
    const out: CalendarEvent[] = [];

    // Filings
    for (const f of SEED_FILINGS) {
      const state = filingState[f.id] ?? {};
      if (state.status === "Filed") continue;
      const due = state.nextDueDate ?? f.nextDueDate;
      if (due) {
        out.push({
          id: `filing:${f.id}`,
          date: due,
          title: f.filingType,
          kind: "filing",
          entitySlug: f.organizationSlug,
          href: "/app/compliance/filings",
        });
      }
    }

    // Licenses
    for (const l of KNOWN_LICENSES) {
      const exp = licenseOverrides[l.id]?.expiresDate ?? l.expiresDate;
      if (exp) {
        out.push({
          id: `license:${l.id}`,
          date: exp,
          title: `${l.licenseType} expires`,
          kind: "license",
          entitySlug: l.organizationSlug,
          href: "/app/compliance/licenses",
        });
      }
    }

    // Domains
    for (const d of DOMAINS) {
      const exp = domainOverrides[d.domain]?.expirationIso ?? d.expirationIso;
      if (exp) {
        out.push({
          id: `domain:${d.domain}`,
          date: exp,
          title: `${d.domain} renewal`,
          kind: "domain",
          href: "/app/domains",
        });
      }
    }

    // Raises — milestones from pitches
    for (const p of PITCHES) {
      for (let mi = 0; mi < p.milestones.length; mi++) {
        const m = p.milestones[mi];
        const iso = parseMilestoneToIso(m.date);
        if (iso) {
          out.push({
            id: `raise:${p.slug}:${mi}`,
            date: iso,
            title: `${p.legalEntity.replace(/, LLC$/, "")}: ${m.label}`,
            kind: "raise",
            entitySlug: p.slug,
            href: `/app/crowdfund/${p.slug}/form-c`,
          });
        }
      }
    }

    // Aggregated (music releases, music bookings, social posts,
    // mail-suggested events) — dedupe by id keeping the aggregator's
    // version if a seed-side event ever happened to share an id.
    const seenIds = new Set(out.map((e) => e.id));
    for (const a of aggregated) {
      // Only include kinds the calendar knows how to color; "bill" and
      // unknown future kinds fall through.
      if (
        a.kind !== "music-release" &&
        a.kind !== "music-booking" &&
        a.kind !== "social-post" &&
        a.kind !== "mail-suggested-event"
      ) {
        continue;
      }
      if (seenIds.has(a.id)) {
        // Replace the seed-side entry with the aggregator's.
        const idx = out.findIndex((e) => e.id === a.id);
        if (idx >= 0) out.splice(idx, 1);
      }
      seenIds.add(a.id);
      out.push({
        id: a.id,
        date: a.date,
        title: a.title,
        kind: a.kind,
        entitySlug: a.entitySlug,
        href: a.href ?? "/app/calendar",
      });
    }

    return out.filter((e) => kindFilters.has(e.kind));
  }, [filingState, licenseOverrides, domainOverrides, aggregated, kindFilters]);

  const monthStart = new Date(cursor.getFullYear(), cursor.getMonth(), 1);
  const startDayOfWeek = monthStart.getDay();

  // Build a 6x7 grid
  const grid: Array<{ date: Date; isCurrentMonth: boolean; events: CalendarEvent[] }> = [];
  const gridStart = new Date(monthStart);
  gridStart.setDate(gridStart.getDate() - startDayOfWeek);
  for (let i = 0; i < 42; i++) {
    const d = new Date(gridStart);
    d.setDate(gridStart.getDate() + i);
    const iso = d.toISOString().slice(0, 10);
    grid.push({
      date: d,
      isCurrentMonth: d.getMonth() === cursor.getMonth(),
      events: events.filter((e) => e.date === iso),
    });
  }

  function prev() {
    setCursor(new Date(cursor.getFullYear(), cursor.getMonth() - 1, 1));
  }
  function next() {
    setCursor(new Date(cursor.getFullYear(), cursor.getMonth() + 1, 1));
  }
  function jumpToday() {
    setCursor(new Date(today.getFullYear(), today.getMonth(), 1));
  }

  function toggleKind(k: EventKind) {
    const next = new Set(kindFilters);
    if (next.has(k)) next.delete(k);
    else next.add(k);
    setKindFilters(next);
  }

  const monthLabel = cursor.toLocaleDateString("en-US", { month: "long", year: "numeric" });
  const monthEventCount = events.filter((e) => {
    const d = new Date(e.date);
    return d.getMonth() === cursor.getMonth() && d.getFullYear() === cursor.getFullYear();
  }).length;

  return (
    <div className="space-y-6">
      <Card>
        <CardContent className="p-4 flex items-center justify-between flex-wrap gap-3">
          <div className="flex items-center gap-2">
            <Button variant="ghost" size="sm" onClick={prev}>←</Button>
            <div className="min-w-[160px] text-center font-medium">{monthLabel}</div>
            <Button variant="ghost" size="sm" onClick={next}>→</Button>
            <Button variant="outline" size="sm" onClick={jumpToday}>Today</Button>
          </div>
          <div className="flex items-center gap-1.5 flex-wrap">
            {ALL_KINDS.map((k) => {
              const active = kindFilters.has(k);
              return (
                <button
                  key={k}
                  onClick={() => toggleKind(k)}
                  className={`text-xs px-2.5 py-1 rounded-full border transition-colors inline-flex items-center gap-1.5 ${
                    active ? "bg-foreground text-background border-foreground" : "border-input text-muted-foreground hover:bg-accent"
                  }`}
                >
                  <span className={`inline-block w-2 h-2 rounded-full ${KIND_COLOR[k]}`} />
                  {KIND_LABEL[k]}
                </button>
              );
            })}
          </div>
          <div className="text-xs text-muted-foreground">
            {monthEventCount} event{monthEventCount === 1 ? "" : "s"} this month
          </div>
        </CardContent>
      </Card>

      <Card>
        <CardContent className="p-0">
          {/* Day-of-week header */}
          <div className="grid grid-cols-7 border-b section-label">
            {["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].map((d) => (
              <div key={d} className="px-2 py-2 text-center">{d}</div>
            ))}
          </div>

          <div className="grid grid-cols-7">
            {grid.map((cell, i) => {
              const isToday = cell.date.toDateString() === today.toDateString();
              return (
                <div
                  key={i}
                  className={`min-h-[120px] border-b border-r p-1.5 text-xs ${
                    cell.isCurrentMonth ? "bg-background" : "bg-muted/30 text-muted-foreground/70"
                  } ${(i + 1) % 7 === 0 ? "border-r-0" : ""}`}
                >
                  <div className={`flex items-center justify-between mb-1`}>
                    <span className={`${isToday ? "rounded-full bg-foreground text-background w-5 h-5 inline-flex items-center justify-center text-[10px] font-semibold" : ""}`}>
                      {cell.date.getDate()}
                    </span>
                    {cell.events.length > 2 && (
                      <span className="text-[9px] text-muted-foreground">+{cell.events.length - 2}</span>
                    )}
                  </div>
                  <div className="space-y-1">
                    {cell.events.slice(0, 3).map((e) => (
                      <Link
                        key={e.id}
                        href={e.href}
                        className="block rounded px-1.5 py-0.5 text-[10px] leading-tight hover:bg-accent group"
                        title={e.title}
                      >
                        <span className={`inline-block w-1.5 h-1.5 rounded-full mr-1.5 align-middle ${KIND_COLOR[e.kind]}`} />
                        <span className="truncate inline-block max-w-[85%] align-middle">{e.title}</span>
                      </Link>
                    ))}
                  </div>
                </div>
              );
            })}
          </div>
        </CardContent>
      </Card>

      {/* List view of next 30 days for quick scanning */}
      <Card>
        <CardContent className="p-6">
          <h3 className="text-base font-semibold mb-3">Next 30 days — chronological</h3>
          <UpcomingList events={events} days={30} />
        </CardContent>
      </Card>
    </div>
  );
}

function UpcomingList({ events, days }: { events: CalendarEvent[]; days: number }) {
  const today = new Date().toISOString().slice(0, 10);
  const cutoff = new Date();
  cutoff.setDate(cutoff.getDate() + days);
  const cutoffIso = cutoff.toISOString().slice(0, 10);

  const upcoming = events
    .filter((e) => e.date >= today && e.date <= cutoffIso)
    .sort((a, b) => a.date.localeCompare(b.date));

  if (upcoming.length === 0) {
    return <p className="text-sm text-muted-foreground">Nothing in the next {days} days.</p>;
  }

  return (
    <ul className="space-y-2">
      {upcoming.map((e) => {
        const org = e.entitySlug ? ALL_ORGANIZATIONS.find((o) => o.slug === e.entitySlug) : undefined;
        return (
          <li key={e.id}>
            <Link
              href={e.href}
              className="flex items-center justify-between rounded-md border bg-background p-3 hover:bg-accent transition-colors text-sm"
            >
              <div className="flex items-center gap-3 min-w-0">
                <span className={`inline-block w-2 h-2 rounded-full ${KIND_COLOR[e.kind]} shrink-0`} />
                <div className="min-w-0">
                  <div className="font-medium truncate">{e.title}</div>
                  <div className="text-xs text-muted-foreground">
                    <Badge variant="outline" className="text-[10px] mr-1.5">{KIND_LABEL[e.kind]}</Badge>
                    {org && <span>{org.emoji} {org.name}</span>}
                  </div>
                </div>
              </div>
              <div className="text-xs font-mono tabular-nums shrink-0 ml-3">
                {new Date(e.date).toLocaleDateString("en-US", { month: "short", day: "numeric" })}
              </div>
            </Link>
          </li>
        );
      })}
    </ul>
  );
}

function parseMilestoneToIso(label: string): string | null {
  // Inputs like "Q2 2026", "Q3 2027", "Jan 2027" etc.
  const qMatch = /^Q([1-4])\s+(\d{4})$/.exec(label.trim());
  if (qMatch) {
    const quarter = parseInt(qMatch[1], 10);
    const year = parseInt(qMatch[2], 10);
    // Use mid-quarter date (Feb 15, May 15, Aug 15, Nov 15)
    const month = (quarter - 1) * 3 + 1;
    return new Date(year, month, 15).toISOString().slice(0, 10);
  }
  // Fallback: try Date.parse
  const ts = Date.parse(label);
  if (!isNaN(ts)) return new Date(ts).toISOString().slice(0, 10);
  return null;
}
