/**
 * Orchestrator layout with a split list/detail experience.
 */

import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useParams, useNavigate, useSearchParams } from "react-router-dom";
import { toast } from "sonner";

import { Button } from "@/components/ui/button";
import { Drawer, DrawerClose, DrawerContent } from "@/components/ui/drawer";

import { ManualImportSheet } from "../components";
import * as api from "../api";
import type { JobSource } from "../../shared/types";
import { DEFAULT_SORT } from "./orchestrator/constants";
import type { FilterTab, JobSort } from "./orchestrator/constants";
import { JobDetailPanel } from "./orchestrator/JobDetailPanel";
import { JobListPanel } from "./orchestrator/JobListPanel";
import { OrchestratorFilters } from "./orchestrator/OrchestratorFilters";
import { OrchestratorHeader } from "./orchestrator/OrchestratorHeader";
import { OrchestratorSummary } from "./orchestrator/OrchestratorSummary";
import { useFilteredJobs } from "./orchestrator/useFilteredJobs";
import { useOrchestratorData } from "./orchestrator/useOrchestratorData";
import { usePipelineSources } from "./orchestrator/usePipelineSources";
import { getJobCounts } from "./orchestrator/utils";

export const OrchestratorPage: React.FC = () => {
  const { tab, jobId } = useParams<{ tab: string; jobId?: string }>();
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();

  const activeTab = useMemo(() => {
    const validTabs: FilterTab[] = ["ready", "discovered", "applied", "all"];
    if (tab && validTabs.includes(tab as FilterTab)) {
      return tab as FilterTab;
    }
    return "ready";
  }, [tab]);

  // Helper to change URL while preserving search params
  const navigateWithContext = useCallback(
    (newTab: string, newJobId?: string | null, isReplace = false) => {
      const search = searchParams.toString();
      const suffix = search ? `?${search}` : "";
      const path = newJobId ? `/${newTab}/${newJobId}${suffix}` : `/${newTab}${suffix}`;
      navigate(path, { replace: isReplace });
    },
    [navigate, searchParams],
  );

  const selectedJobId = jobId || null;

  // Sync searchQuery with URL
  const searchQuery = searchParams.get("q") || "";
  const setSearchQuery = (q: string) => {
    setSearchParams(
      (prev) => {
        if (q) prev.set("q", q);
        else prev.delete("q");
        return prev;
      },
      { replace: true },
    );
  };

  // Sync sourceFilter with URL
  const sourceFilter = (searchParams.get("source") as JobSource | "all") || "all";
  const setSourceFilter = (source: JobSource | "all") => {
    setSearchParams(
      (prev) => {
        if (source !== "all") prev.set("source", source);
        else prev.delete("source");
        return prev;
      },
      { replace: true },
    );
  };

  // Sync sort with URL
  const sort = useMemo((): JobSort => {
    const s = searchParams.get("sort");
    if (!s) return DEFAULT_SORT;
    const [key, direction] = s.split("-");
    return { key: key as any, direction: direction as any };
  }, [searchParams]);

  const setSort = (newSort: JobSort) => {
    setSearchParams(
      (prev) => {
        if (newSort.key === DEFAULT_SORT.key && newSort.direction === DEFAULT_SORT.direction) {
          prev.delete("sort");
        } else {
          prev.set("sort", `${newSort.key}-${newSort.direction}`);
        }
        return prev;
      },
      { replace: true },
    );
  };

  // Effect to sync URL if it was invalid
  useEffect(() => {
    const validTabs: FilterTab[] = ["ready", "discovered", "applied", "all"];
    if (tab && !validTabs.includes(tab as FilterTab)) {
      navigateWithContext("ready", null, true);
    }
  }, [tab, navigateWithContext]);

  const [navOpen, setNavOpen] = useState(false);
  const [isManualImportOpen, setIsManualImportOpen] = useState(false);
  const [isDetailDrawerOpen, setIsDetailDrawerOpen] = useState(false);
  const [isDesktop, setIsDesktop] = useState(
    () => (typeof window !== "undefined" ? window.matchMedia("(min-width: 1024px)").matches : false),
  );

  const setActiveTab = (newTab: FilterTab) => {
    navigateWithContext(newTab, selectedJobId);
  };

  const handleSelectJobId = (id: string | null) => {
    navigateWithContext(activeTab, id);
  };

  const { pipelineSources, setPipelineSources, toggleSource } = usePipelineSources();
  const { jobs, stats, settings, isLoading, isPipelineRunning, setIsPipelineRunning, loadJobs } = useOrchestratorData();

  const showSponsorInfo = settings?.showSponsorInfo ?? true;

  const activeJobs = useFilteredJobs(jobs, activeTab, sourceFilter, searchQuery, sort);
  const counts = useMemo(() => getJobCounts(jobs), [jobs]);
  const selectedJob = useMemo(
    () => (selectedJobId ? jobs.find((job) => job.id === selectedJobId) ?? null : null),
    [jobs, selectedJobId],
  );

  const handleManualImported = useCallback(
    async (importedJobId: string) => {
      // Refresh jobs and navigate to the new job in discovered tab
      await loadJobs();
      navigateWithContext("discovered", importedJobId);
    },
    [loadJobs, navigateWithContext],
  );

  const handleRunPipeline = async () => {
    try {
      setIsPipelineRunning(true);
      await api.runPipeline({ sources: pipelineSources });
      toast.message("Pipeline started", {
        description: `Sources: ${pipelineSources.join(", ")}. This may take a few minutes.`,
      });

      const pollInterval = setInterval(async () => {
        try {
          const status = await api.getPipelineStatus();
          if (!status.isRunning) {
            clearInterval(pollInterval);
            setIsPipelineRunning(false);
            await loadJobs();
            toast.success("Pipeline completed");
          }
        } catch {
          // Ignore errors
        }
      }, 5000);
    } catch (error) {
      setIsPipelineRunning(false);
      const message = error instanceof Error ? error.message : "Failed to start pipeline";
      toast.error(message);
    }
  };

  const handleSelectJob = (id: string) => {
    handleSelectJobId(id);
    if (!isDesktop) {
      setIsDetailDrawerOpen(true);
    }
  };

  useEffect(() => {
    if (activeJobs.length === 0) {
      if (selectedJobId) handleSelectJobId(null);
      return;
    }
    if (!selectedJobId || !activeJobs.some((job) => job.id === selectedJobId)) {
      // Auto-select first job ONLY on desktop
      if (isDesktop) {
        navigateWithContext(activeTab, activeJobs[0].id, true);
      }
    }
  }, [activeJobs, selectedJobId, isDesktop, activeTab, navigateWithContext]);

  useEffect(() => {
    if (!selectedJobId) {
      setIsDetailDrawerOpen(false);
    } else if (!isDesktop) {
      setIsDetailDrawerOpen(true);
    }
  }, [selectedJobId, isDesktop]);

  useEffect(() => {
    if (typeof window === "undefined") return;
    const media = window.matchMedia("(min-width: 1024px)");
    const handleChange = () => setIsDesktop(media.matches);
    handleChange();
    if (media.addEventListener) {
      media.addEventListener("change", handleChange);
      return () => media.removeEventListener("change", handleChange);
    }
    media.addListener(handleChange);
    return () => media.removeListener(handleChange);
  }, []);

  useEffect(() => {
    if (isDesktop && isDetailDrawerOpen) {
      setIsDetailDrawerOpen(false);
    }
  }, [isDesktop, isDetailDrawerOpen]);

  const onDrawerOpenChange = (open: boolean) => {
    setIsDetailDrawerOpen(open);
    if (!open && !isDesktop) {
      // Clear job ID from URL when closing drawer on mobile
      handleSelectJobId(null);
    }
  };

  return (
    <>
      <OrchestratorHeader
        navOpen={navOpen}
        onNavOpenChange={setNavOpen}
        isPipelineRunning={isPipelineRunning}
        pipelineSources={pipelineSources}
        onToggleSource={toggleSource}
        onSetPipelineSources={setPipelineSources}
        onRunPipeline={handleRunPipeline}
        onOpenManualImport={() => setIsManualImportOpen(true)}
      />

      <main className="container mx-auto max-w-7xl space-y-6 px-4 py-6 pb-12">
        <OrchestratorSummary stats={stats} isPipelineRunning={isPipelineRunning} />

        {/* Main content: tabs/filters -> list/detail */}
        <section className="space-y-4">
          <OrchestratorFilters
            activeTab={activeTab}
            onTabChange={setActiveTab}
            counts={counts}
            searchQuery={searchQuery}
            onSearchQueryChange={setSearchQuery}
            sourceFilter={sourceFilter}
            onSourceFilterChange={setSourceFilter}
            sort={sort}
            onSortChange={setSort}
          />

          {/* List/Detail grid - directly under tabs, no extra section */}
          <div className="grid gap-4 lg:grid-cols-[minmax(0,400px)_minmax(0,1fr)]">
            {/* Primary region: Job list with highest visual weight */}
            <JobListPanel
              isLoading={isLoading}
              jobs={jobs}
              activeJobs={activeJobs}
              selectedJobId={selectedJobId}
              activeTab={activeTab}
              searchQuery={searchQuery}
              onSelectJob={handleSelectJob}
            />

            {/* Inspector panel: visually subordinate to list */}
            {isDesktop && (
              <div className="min-w-0 rounded-lg border border-border/40 bg-muted/5 p-4 lg:sticky lg:top-24 lg:self-start lg:max-h-[calc(100vh-8rem)] lg:overflow-y-auto">
                <JobDetailPanel
                  activeTab={activeTab}
                  activeJobs={activeJobs}
                  selectedJob={selectedJob}
                  onSelectJobId={handleSelectJobId}
                  onJobUpdated={loadJobs}
                  onSetActiveTab={setActiveTab}
                  showSponsorInfo={showSponsorInfo}
                />
              </div>
            )}
          </div>
        </section>
      </main>

      <ManualImportSheet
        open={isManualImportOpen}
        onOpenChange={setIsManualImportOpen}
        onImported={handleManualImported}
      />

      {!isDesktop && (
        <Drawer open={isDetailDrawerOpen} onOpenChange={onDrawerOpenChange}>
          <DrawerContent className="max-h-[90vh]">
            <div className="flex items-center justify-between px-4 pt-2">
              <div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Job details</div>
              <DrawerClose asChild>
                <Button variant="ghost" size="sm" className="h-8 px-2 text-xs">
                  Close
                </Button>
              </DrawerClose>
            </div>
            <div className="max-h-[calc(90vh-3.5rem)] overflow-y-auto px-4 pb-6 pt-3">
              <JobDetailPanel
                activeTab={activeTab}
                activeJobs={activeJobs}
                selectedJob={selectedJob}
                onSelectJobId={handleSelectJobId}
                onJobUpdated={loadJobs}
                onSetActiveTab={setActiveTab}
              />
            </div>
          </DrawerContent>
        </Drawer>
      )}
    </>
  );
};
