"use client";

import { useState, useEffect, useCallback, useMemo, Suspense } from "react";
import { useSession } from "next-auth/react";
import { useRouter, useSearchParams } from "next/navigation";
import Link from "next/link";
import { Upload, CalendarDays, PenSquare, User, Megaphone, Globe } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/components/ui/sheet";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { CalendarGrid } from "@/components/calendar/CalendarGrid";
import { BulkImportModal } from "@/components/calendar/BulkImportModal";
import { SourceFilter } from "@/components/calendar/SourceFilter";
import { PostMetricsBadge } from "@/components/analytics/PostMetricsBadge";
import type { PostSource } from "@/components/calendar/PostPill";
import type { PostStatus, Network, UserRole, Region } from "@/lib/types";
import { RegionBadge, REGION_BADGE_COLORS } from "@/components/composer/RegionSelector";

interface PostAnalyticsData {
  impressions: number;
  clicks: number;
  shares: number;
  comments: number;
  reactions: number;
}

interface PostAuthor {
  id: string;
  name: string | null;
  image: string | null;
}

interface PostAccountStatus {
  socialAccount: { id: string; network: string; accountName: string };
  publishStatus: string;
  staggeredPublishAt: string | null;
}

interface Campaign {
  id: string;
  name: string;
  createdAt?: string;
  source?: "HUBSPOT" | "HUMAN";
  _count?: { posts: number };
}

interface CalendarPost {
  id: string;
  content: string;
  status: PostStatus;
  networks: Network[];
  scheduledAt: string;
  originalScheduledAt?: string | null;
  analytics?: PostAnalyticsData[];
  author?: PostAuthor;
  postAccounts?: PostAccountStatus[];
  source?: PostSource;
  campaignId?: string | null;
  campaignName?: string | null;
  region?: Region | null;
  mediaUrls?: string[];
}

// Region → IANA timezone for display purposes (must match lib/region-config.ts)
const REGION_TIMEZONE: Record<string, string> = {
  APAC: "Asia/Kolkata",
  NA: "America/Los_Angeles",
  LATAM: "America/Sao_Paulo",
  EMEA: "Europe/Berlin",
  GLOBAL: "America/Los_Angeles",
};

/** Format a date in the given region's timezone (defaults to GLOBAL/PT) */
function formatInRegionTz(dateStr: string, region: string | "all"): string {
  const tz = REGION_TIMEZONE[region === "all" ? "GLOBAL" : region] ?? REGION_TIMEZONE.GLOBAL;
  return new Date(dateStr).toLocaleString(undefined, {
    timeZone: tz,
    timeZoneName: "short",
  });
}

const STATUS_LABELS: Record<PostStatus, string> = {
  DRAFT: "Draft",
  SCHEDULED: "Scheduled",
  PUBLISHED: "Published",
  FAILED: "Failed",
  PENDING_APPROVAL: "Pending Approval",
  REJECTED: "Rejected",
};

const STATUS_COLORS: Record<PostStatus, string> = {
  DRAFT: "bg-gray-100 text-gray-700",
  SCHEDULED: "bg-blue-100 text-blue-700",
  PUBLISHED: "bg-green-100 text-green-700",
  FAILED: "bg-red-100 text-red-700",
  PENDING_APPROVAL: "bg-yellow-100 text-yellow-700",
  REJECTED: "bg-orange-100 text-orange-700",
};

export default function CalendarPage() {
  return (
    <Suspense fallback={<div className="py-12 text-center text-sm text-gray-500">Loading calendar...</div>}>
      <CalendarPageInner />
    </Suspense>
  );
}

function CalendarPageInner() {
  const { data: session } = useSession();
  const router = useRouter();
  const searchParams = useSearchParams();
  const role = (session?.user as { role?: UserRole })?.role;
  const isViewer = role === "VIEWER";

  const [view, setView] = useState<"month" | "week">("month");
  const [selectedPost, setSelectedPost] = useState<CalendarPost | null>(null);
  const [posts, setPosts] = useState<CalendarPost[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [bulkImportOpen, setBulkImportOpen] = useState(false);
  const [averages, setAverages] = useState<{ engagementRate: number } | null>(null);
  const [authorFilter, setAuthorFilter] = useState<string>("all");
  const [sourceFilter, setSourceFilter] = useState<PostSource | "ALL">("ALL");
  const [campaignFilter, setCampaignFilter] = useState<string>(searchParams.get("campaign") ?? "all");
  const [regionFilter, setRegionFilter] = useState<Region | "all">("all");
  const [campaigns, setCampaigns] = useState<Campaign[]>([]);
  const [filterSources, setFilterSources] = useState<string[]>([]);
  const [filterRegions, setFilterRegions] = useState<string[]>([]);

  useEffect(() => {
    fetch("/api/v1/analytics/average?days=30")
      .then((r) => (r.ok ? r.json() : null))
      .then((data) => {
        if (data) setAverages({ engagementRate: data.avgEngagementRate });
      })
      .catch(() => {});

    fetch("/api/v1/campaigns")
      .then((r) => (r.ok ? r.json() : []))
      .then((data) => setCampaigns(Array.isArray(data) ? data : []))
      .catch(() => {});

    fetch("/api/v1/posts/filters")
      .then((r) => (r.ok ? r.json() : null))
      .then((data) => {
        if (data) {
          if (Array.isArray(data.sources)) setFilterSources(data.sources);
          if (Array.isArray(data.regions)) setFilterRegions(data.regions);
        }
      })
      .catch(() => {});
  }, []);

  const fetchPosts = useCallback(async () => {
    try {
      setError("");
      const res = await fetch("/api/v1/posts?limit=200&status=SCHEDULED&status=PUBLISHED&status=PENDING_APPROVAL&status=FAILED");
      if (!res.ok) throw new Error("Failed to load posts");
      const data = await res.json();
      setPosts(
        data.map((p: Record<string, unknown>) => ({
          id: p.id as string,
          content: p.content as string,
          status: p.status as PostStatus,
          networks: typeof p.networks === "string" ? JSON.parse(p.networks as string) : (p.networks as Network[]),
          scheduledAt: (p.scheduledAt ?? p.createdAt) as string,
          originalScheduledAt: p.originalScheduledAt as string | null | undefined,
          analytics: (p.analytics as PostAnalyticsData[] | undefined) ?? [],
          author: p.author as PostAuthor | undefined,
          postAccounts: p.postAccounts as PostAccountStatus[] | undefined,
          source: p.source as PostSource | undefined,
          campaignId: p.campaignId as string | null | undefined,
          campaignName: (p.campaign as { name?: string } | null)?.name ?? null,
          region: (p.region as Region | null | undefined) ?? null,
          mediaUrls: (() => { const m = p.mediaUrls; if (Array.isArray(m)) return m as string[]; if (typeof m === "string") { try { return JSON.parse(m) as string[]; } catch { return []; } } return []; })(),
        }))
      );
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to load posts");
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    fetchPosts();
  }, [fetchPosts]);

  const handleDelete = async (id: string) => {
    if (!confirm("Delete this post?")) return;
    try {
      const res = await fetch(`/api/v1/posts/${id}`, { method: "DELETE" });
      if (!res.ok) throw new Error("Failed to delete post");
      setSelectedPost(null);
      fetchPosts();
    } catch (err) {
      alert(err instanceof Error ? err.message : "Failed to delete post");
    }
  };

  const handleEdit = (post: CalendarPost) => {
    router.push(`/dashboard/compose?edit=${post.id}`);
  };

  const handleNewPost = (date: Date) => {
    const yyyy = date.getFullYear();
    const mm = String(date.getMonth() + 1).padStart(2, "0");
    const dd = String(date.getDate()).padStart(2, "0");
    router.push(`/dashboard/compose?date=${yyyy}-${mm}-${dd}`);
  };

  const uniqueAuthors = useMemo(() => {
    const map = new Map<string, PostAuthor>();
    posts.forEach((p) => {
      if (p.author) map.set(p.author.id, p.author);
    });
    return Array.from(map.values());
  }, [posts]);

  // Cascade: filter campaigns by selected source
  const filteredCampaigns = useMemo(() => {
    if (sourceFilter === "ALL") return campaigns;
    return campaigns.filter((c) => c.source === sourceFilter);
  }, [campaigns, sourceFilter]);

  // Reset campaign selection if it no longer appears in filtered campaigns
  useEffect(() => {
    if (campaignFilter === "all") return;
    if (!filteredCampaigns.some((c) => c.id === campaignFilter)) {
      setCampaignFilter("all");
    }
  }, [filteredCampaigns, campaignFilter]);

  const filteredPosts = useMemo(() => {
    let result = posts;
    if (authorFilter !== "all") {
      result = result.filter((p) => p.author?.id === authorFilter);
    }
    if (campaignFilter !== "all") {
      result = result.filter((p) => p.campaignId === campaignFilter);
    }
    if (regionFilter !== "all") {
      result = result.filter((p) => p.region === regionFilter);
    }
    return result;
  }, [posts, authorFilter, campaignFilter, regionFilter]);

  return (
    <div className="space-y-4 overflow-x-hidden">
      <div className="border-b border-gray-100 -mx-4 md:-mx-6 -mt-4 md:-mt-6 px-4 sm:px-8 py-4 sm:py-5 mb-4 sm:mb-6 flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
        <div>
          <h1 className="text-2xl font-semibold text-gray-900">Content Calendar</h1>
          <p className="text-sm text-gray-500">Plan and schedule your social media content</p>
        </div>
        <div className="flex flex-wrap items-center gap-2 w-full sm:w-auto">
          {uniqueAuthors.length > 1 && (
            <Select value={authorFilter} onValueChange={(v) => setAuthorFilter(v ?? "all")}>
              <SelectTrigger className="w-[130px] sm:w-[160px] h-8 text-xs border-gray-200">
                <User className="h-3 w-3 mr-1 text-gray-500" />
                <span className="truncate">
                  {authorFilter === "all"
                    ? "All Authors"
                    : uniqueAuthors.find((a) => a.id === authorFilter)?.name ?? "All Authors"}
                </span>
              </SelectTrigger>
              <SelectContent className="z-50">
                <SelectItem value="all">All Authors</SelectItem>
                {uniqueAuthors.map((a) => (
                  <SelectItem key={a.id} value={a.id}>
                    {a.name ?? "Unknown"}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          )}
          <SourceFilter value={sourceFilter} onChange={setSourceFilter} sources={filterSources} />
          {filteredCampaigns.length > 0 && (
            <Select value={campaignFilter} onValueChange={(v) => setCampaignFilter(v ?? "all")}>
              <SelectTrigger className="w-[130px] sm:w-[160px] h-8 text-xs border-gray-200">
                <Megaphone className="h-3 w-3 mr-1 text-gray-500" />
                <span className="truncate">
                  {campaignFilter === "all"
                    ? "All Campaigns"
                    : filteredCampaigns.find((c) => c.id === campaignFilter)?.name ?? "All Campaigns"}
                </span>
              </SelectTrigger>
              <SelectContent className="z-50">
                <SelectItem value="all">All Campaigns</SelectItem>
                {filteredCampaigns.map((c) => (
                  <SelectItem key={c.id} value={c.id}>
                    {c.name}{c._count?.posts != null ? ` (${c._count.posts} post${c._count.posts !== 1 ? "s" : ""})` : ""}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          )}
          <div className="flex items-center gap-1.5">
            <Select value={regionFilter} onValueChange={(v) => setRegionFilter((v ?? "all") as Region | "all")}>
              <SelectTrigger className="w-[130px] sm:w-[160px] h-8 text-xs border-gray-200" data-testid="calendar-region-filter">
                <Globe className="h-3 w-3 mr-1 text-gray-500" />
                <SelectValue placeholder="All Regions" />
              </SelectTrigger>
              <SelectContent className="z-50">
                <SelectItem value="all">All Regions</SelectItem>
                {filterRegions.map((r) => (
                  <SelectItem key={r} value={r}>{r === "GLOBAL" ? "Global" : r}</SelectItem>
                ))}
              </SelectContent>
            </Select>
            {(() => {
              const tz = REGION_TIMEZONE[regionFilter === "all" ? "GLOBAL" : regionFilter];
              const tzLabel = tz ? (() => {
                try {
                  return new Intl.DateTimeFormat("en", { timeZone: tz, timeZoneName: "short" })
                    .formatToParts(new Date())
                    .find(p => p.type === "timeZoneName")?.value ?? null;
                } catch { return null; }
              })() : null;
              return tzLabel ? (
                <span className="text-[11px] text-gray-400 whitespace-nowrap" data-testid="calendar-tz-label">({tzLabel})</span>
              ) : null;
            })()}
          </div>
          {!isViewer && (
            <Button
              variant="outline"
              size="sm"
              className="border-gray-200 text-gray-700 hover:bg-gray-50"
              onClick={() => setBulkImportOpen(true)}
            >
              <Upload className="h-3.5 w-3.5 mr-1.5" />
              <span className="hidden sm:inline">Bulk Import</span>
              <span className="sm:hidden">Import</span>
            </Button>
          )}
          <div className="flex rounded-lg border border-gray-200">
            <Button
              variant={view === "month" ? "default" : "ghost"}
              size="sm"
              className={view === "month" ? "bg-gray-900 hover:bg-gray-800 text-white" : "text-gray-700 hover:bg-gray-50"}
              onClick={() => setView("month")}
            >
              Month
            </Button>
            <Button
              variant={view === "week" ? "default" : "ghost"}
              size="sm"
              className={view === "week" ? "bg-gray-900 hover:bg-gray-800 text-white" : "text-gray-700 hover:bg-gray-50"}
              onClick={() => setView("week")}
            >
              Week
            </Button>
          </div>
        </div>
      </div>

      {/* Status legend */}
      <div className="flex flex-wrap gap-3 text-xs">
        {(Object.entries(STATUS_COLORS) as [PostStatus, string][]).map(([status, cls]) => (
          <div key={status} className="flex items-center gap-1.5">
            <span className={`inline-block h-2.5 w-2.5 rounded ${cls.split(" ")[0]}`} />
            <span className="text-gray-500">{STATUS_LABELS[status]}</span>
          </div>
        ))}
      </div>

      {error && (
        <div className="rounded-lg bg-red-50 border border-red-200 px-4 py-3 text-sm text-red-700">
          {error}
        </div>
      )}

      {loading ? (
        <div className="flex items-center justify-center py-20">
          <div className="text-sm text-gray-500">Loading calendar...</div>
        </div>
      ) : posts.length === 0 ? (
        <div className="flex flex-col items-center justify-center rounded-lg border border-dashed border-gray-300 py-20">
          <CalendarDays className="h-12 w-12 text-gray-300 mb-4" />
          <p className="text-sm font-medium text-gray-600">Your calendar is empty</p>
          <p className="text-xs text-gray-500 mt-1 max-w-xs text-center">
            Schedule your first post to see it here. Use the compose page to create and schedule content.
          </p>
          {!isViewer && (
            <Link href="/dashboard/compose" className="mt-4">
              <Button size="sm" className="bg-gray-900 hover:bg-gray-800 text-white">
                <PenSquare className="h-3.5 w-3.5 mr-1.5" />
                Create Your First Post
              </Button>
            </Link>
          )}
        </div>
      ) : (
        <CalendarGrid
          posts={filteredPosts}
          view={view}
          onPostClick={(post) => setSelectedPost(post)}
          onNewPost={isViewer ? undefined : handleNewPost}
          readOnly={isViewer}
          sourceFilter={sourceFilter}
        />
      )}

      {/* Post detail slide-over */}
      <Sheet open={!!selectedPost} onOpenChange={() => setSelectedPost(null)}>
        <SheetContent>
          {selectedPost && (
            <>
              <SheetHeader>
                <SheetTitle className="text-gray-900">Post Details</SheetTitle>
              </SheetHeader>
              <div className="mt-6 space-y-4">
                {selectedPost.author && (
                  <div className="flex items-center gap-2">
                    {selectedPost.author.image ? (
                      <img
                        src={selectedPost.author.image}
                        alt=""
                        className="h-6 w-6 rounded-full"
                      />
                    ) : (
                      <span className="flex h-6 w-6 items-center justify-center rounded-full bg-gray-200 text-xs font-medium text-gray-600">
                        {(selectedPost.author.name ?? "?").charAt(0).toUpperCase()}
                      </span>
                    )}
                    <span className="text-sm text-gray-600">
                      by {selectedPost.author.name ?? "Unknown"}
                    </span>
                  </div>
                )}
                <div>
                  <p className="text-xs font-medium text-gray-500 mb-1">Status</p>
                  <Badge className={STATUS_COLORS[selectedPost.status]}>
                    {STATUS_LABELS[selectedPost.status]}
                  </Badge>
                </div>
                {selectedPost.region && (
                  <div>
                    <p className="text-xs font-medium text-gray-500 mb-1">Region</p>
                    <RegionBadge region={selectedPost.region} />
                  </div>
                )}
                <div>
                  <p className="text-xs font-medium text-gray-500 mb-1">Networks</p>
                  <div className="flex gap-1">
                    {selectedPost.networks.map((n) => (
                      <Badge key={n} variant="outline" className="border-gray-200">{n}</Badge>
                    ))}
                  </div>
                </div>
                <div>
                  <p className="text-xs font-medium text-gray-500 mb-1">Scheduled</p>
                  <p className="text-sm text-gray-900">{formatInRegionTz(selectedPost.scheduledAt, regionFilter)}</p>
                  {regionFilter !== "all" && (
                    <p className="text-xs text-gray-400 mt-0.5">Showing in {regionFilter} timezone</p>
                  )}
                  {selectedPost.originalScheduledAt && selectedPost.originalScheduledAt !== selectedPost.scheduledAt && (
                    <p className="text-xs text-gray-400 mt-1" data-testid="original-schedule">
                      Originally scheduled: {formatInRegionTz(selectedPost.originalScheduledAt, regionFilter)}
                    </p>
                  )}
                </div>
                {/* Bug 5: Per-network publish status */}
                {selectedPost.postAccounts && selectedPost.postAccounts.length > 0 && (
                  <div>
                    <p className="text-xs font-medium text-gray-500 mb-1">Network Status</p>
                    <div className="space-y-1">
                      {selectedPost.postAccounts.map((pa) => (
                        <div key={pa.socialAccount.id} className="flex items-center gap-2 text-xs" data-testid="network-status">
                          <span className="font-medium text-gray-700">{pa.socialAccount.network}:</span>
                          <span className={pa.publishStatus === "PUBLISHED" ? "text-green-600" : pa.publishStatus === "FAILED" ? "text-red-600" : "text-amber-600"}>
                            {pa.publishStatus === "PUBLISHED" ? "Published ✅" : pa.publishStatus === "FAILED" ? "Failed ❌" : "Pending ⏳"}
                          </span>
                          {pa.socialAccount.accountName && (
                            <span className="text-gray-400">@{pa.socialAccount.accountName}</span>
                          )}
                        </div>
                      ))}
                    </div>
                  </div>
                )}
                <div>
                  <p className="text-xs font-medium text-gray-500 mb-1">Content</p>
                  <p className="text-sm text-gray-900 whitespace-pre-wrap">{selectedPost.content}</p>
                </div>
                {selectedPost.status === "PUBLISHED" && (
                  <div>
                    <p className="text-xs font-medium text-gray-500 mb-1">Performance</p>
                    <PostMetricsBadge
                      analytics={selectedPost.analytics ?? []}
                      averages={averages}
                    />
                  </div>
                )}
                {!isViewer && !["PUBLISHED", "FAILED"].includes(selectedPost.status) && (
                  <div className="flex gap-2 pt-4">
                    <Button
                      variant="outline"
                      size="sm"
                      className="border-gray-200 text-gray-700 hover:bg-gray-50"
                      onClick={() => handleEdit(selectedPost)}
                    >
                      Edit
                    </Button>
                    <Button
                      variant="destructive"
                      size="sm"
                      onClick={() => handleDelete(selectedPost.id)}
                    >
                      Delete
                    </Button>
                  </div>
                )}
              </div>
            </>
          )}
        </SheetContent>
      </Sheet>

      <BulkImportModal
        open={bulkImportOpen}
        onClose={() => setBulkImportOpen(false)}
        onComplete={() => fetchPosts()}
      />
    </div>
  );
}
