// TicketsPanelRefactored - Split version with reduced complexity
import React, { useState, useCallback, useEffect } from 'react';
import { get } from '../../api.js';
import TicketFilters from './TicketFilters';
import TicketStats from './TicketStats';
import TicketList from './TicketList';
import BulkOperations from './BulkOperations';

const STATUS_COLORS = {
  backlog: "bg-gray-100 text-gray-600",
  todo: "bg-blue-100 text-blue-700",
  in_progress: "bg-amber-100 text-amber-700",
  in_review: "bg-purple-100 text-purple-700",
  done: "bg-emerald-100 text-emerald-700",
  cancelled: "bg-red-100 text-red-600",
};

const PRIORITY_COLORS = {
  critical: "bg-red-200 text-red-800",
  high: "bg-orange-100 text-orange-700",
  medium: "bg-yellow-100 text-yellow-700",
  low: "bg-gray-100 text-gray-600",
};

const JOB_STATUS_COLORS = {
  queued: "bg-gray-100 text-gray-600",
  running: "bg-amber-100 text-amber-700",
  done: "bg-emerald-100 text-emerald-700",
  failed: "bg-red-100 text-red-600",
  cancelled: "bg-gray-200 text-gray-500",
};

// Extracted filtering logic
function useTicketFilters(tickets, selectedMilestone, selectedSprint, filterStatus, filterTool, filterPriority, searchQuery, sortBy, sortOrder) {
  return React.useMemo(() => {
    let result = tickets;
    
    // Apply filters
    if (selectedMilestone) result = result.filter(t => t.milestone_id === selectedMilestone);
    if (selectedSprint) result = result.filter(t => t.sprint_id === selectedSprint);
    if (filterStatus) result = result.filter(t => t.status === filterStatus);
    if (filterTool) result = result.filter(t => t.assigned_tool?.tool === filterTool);
    if (filterPriority) result = result.filter(t => t.priority === filterPriority);
    
    // Search filter
    if (searchQuery.trim()) {
      const q = searchQuery.toLowerCase();
      result = result.filter(t => 
        (t.task || "").toLowerCase().includes(q) ||
        (t.title || "").toLowerCase().includes(q) ||
        (t.description || "").toLowerCase().includes(q) ||
        (t.tags || []).some(tag => tag.toLowerCase().includes(q)) ||
        (t.id || "").toLowerCase().includes(q)
      );
    }
    
    // Sorting
    const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
    const statusOrder = { in_progress: 0, todo: 1, in_review: 2, backlog: 3, done: 4, cancelled: 5 };
    
    result = [...result].sort((a, b) => {
      let comparison = 0;
      switch (sortBy) {
        case "priority":
          comparison = (priorityOrder[a.priority] || 99) - (priorityOrder[b.priority] || 99);
          break;
        case "status":
          comparison = (statusOrder[a.status] || 99) - (statusOrder[b.status] || 99);
          break;
        case "updated":
          comparison = (b.updated_at || 0) - (a.updated_at || 0);
          break;
        case "created":
        default:
          comparison = (b.created_at || 0) - (a.created_at || 0);
          break;
      }
      return sortOrder === "asc" ? -comparison : comparison;
    });
    
    return result;
  }, [tickets, selectedMilestone, selectedSprint, filterStatus, filterTool, filterPriority, searchQuery, sortBy, sortOrder]);
}

// Extracted statistics calculation
function useTicketStats(filtered) {
  const TOOLS = ["vscode", "aider", "claude-code", "windsurf", "cursor", "roo-code", "continue", "copilot", "human"];
  
  return React.useMemo(() => ({
    total: filtered.length,
    todo: filtered.filter(t => t.status === "todo").length,
    in_progress: filtered.filter(t => t.status === "in_progress").length,
    done: filtered.filter(t => t.status === "done").length,
    by_tool: TOOLS.reduce((acc, tool) => {
      const count = filtered.filter(t => t.assigned_tool?.tool === tool).length;
      if (count > 0) acc[tool] = count;
      return acc;
    }, {}),
  }), [filtered]);
}

function useTicketReviewDetail(selectedTicket) {
  const [detail, setDetail] = useState(null);
  const [loadingDetail, setLoadingDetail] = useState(false);
  const [detailError, setDetailError] = useState("");

  const refreshDetail = useCallback(async () => {
    if (!selectedTicket) {
      setDetail(null);
      setDetailError("");
      setLoadingDetail(false);
      return;
    }

    setLoadingDetail(true);
    try {
      const data = await get(`/dashboard/tickets/${selectedTicket}`);
      if (data && data.ok === false) {
        throw new Error(
          typeof data.body === "string"
            ? data.body
            : data.body?.detail || data.body?.message || `Failed to load ticket ${selectedTicket}`
        );
      }
      setDetail(data || null);
      setDetailError("");
    } catch (error) {
      setDetail(null);
      setDetailError(error?.message || `Failed to load ticket ${selectedTicket}`);
    } finally {
      setLoadingDetail(false);
    }
  }, [selectedTicket]);

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

  return { detail, loadingDetail, detailError, refreshDetail };
}

// Extracted data hook
function useTicketsData() {
  const [tickets, setTickets] = useState([]);
  const [sprints, setSprints] = useState([]);
  const [milestones, setMilestones] = useState([]);
  const [loading, setLoading] = useState(true);

  const refreshTickets = useCallback(async () => {
    const data = await get("/dashboard/tickets");
    setTickets(data?.tickets || []);
  }, []);

  const refreshSprints = useCallback(async () => {
    const data = await get("/dashboard/sprints");
    setSprints(data?.sprints || []);
  }, []);

  const refreshMilestones = useCallback(async () => {
    const data = await get("/dashboard/milestones");
    setMilestones(data?.milestones || []);
  }, []);

  const refresh = useCallback(async () => {
    setLoading(true);
    await Promise.all([refreshTickets(), refreshSprints(), refreshMilestones()]);
    setLoading(false);
  }, [refreshTickets, refreshSprints, refreshMilestones]);

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

  return { tickets, sprints, milestones, loading, refresh, refreshTickets, refreshSprints, refreshMilestones };
}

// Main component - reduced complexity
function TicketsPanelRefactored({
  selectedTicket, setSelectedTicket,
  filterStatus: filterStatusProp, setFilterStatus: setFilterStatusProp,
  searchQuery: searchQueryProp, setSearchQuery: setSearchQueryProp,
}) {
  // Data fetching
  const { tickets, sprints, milestones, loading, refresh } = useTicketsData();
  
  // Filter state — use URL-backed props when available
  const [selectedMilestone, setSelectedMilestone] = useState(null);
  const [selectedSprint, setSelectedSprint] = useState(null);
  const [localFilterStatus, setLocalFilterStatus] = useState("");
  const [filterTool, setFilterTool] = useState("");
  const [filterPriority, setFilterPriority] = useState("");
  const [localSearchQuery, setLocalSearchQuery] = useState("");
  const [sortBy, setSortBy] = useState("created");
  const [sortOrder, setSortOrder] = useState("desc");

  const filterStatus = filterStatusProp !== undefined ? filterStatusProp : localFilterStatus;
  const setFilterStatus = setFilterStatusProp || setLocalFilterStatus;
  const searchQuery = searchQueryProp !== undefined ? searchQueryProp : localSearchQuery;
  const setSearchQuery = setSearchQueryProp || setLocalSearchQuery;
  
  // Bulk operations state
  const [selectedTickets, setSelectedTickets] = useState(new Set());
  const { detail: ticketDetail, loadingDetail, detailError, refreshDetail } = useTicketReviewDetail(selectedTicket);
  
  // Computed values
  const filtered = useTicketFilters(tickets, selectedMilestone, selectedSprint, filterStatus, filterTool, filterPriority, searchQuery, sortBy, sortOrder);
  const stats = useTicketStats(filtered);
  
  // Handlers
  const handleRefresh = useCallback(async () => {
    await refresh();
    if (selectedTicket) {
      await refreshDetail();
    }
  }, [refresh, refreshDetail, selectedTicket]);

  const toggleTicketSelection = useCallback((ticketId) => {
    const newSet = new Set(selectedTickets);
    if (newSet.has(ticketId)) {
      newSet.delete(ticketId);
    } else {
      newSet.add(ticketId);
    }
    setSelectedTickets(newSet);
  }, [selectedTickets]);

  const visibleSprints = React.useMemo(() => {
    return sprints.filter(s => !selectedMilestone || s.milestone_id === selectedMilestone);
  }, [sprints, selectedMilestone]);

  if (loading) {
    return <div className="bg-white rounded-lg border p-8 text-center"><p className="text-gray-500">Loading...</p></div>;
  }

  const reviewComments = [...(ticketDetail?.comments || [])].reverse();
  const auditComments = reviewComments.filter((comment) => {
    const author = String(comment.author || "").toLowerCase();
    const content = String(comment.content || "").toLowerCase();
    return author.includes("orchestrator") || author.includes("system") || author.includes("llm") || content.includes("review") || content.includes("decision") || content.includes("analysis");
  });
  const latestComment = auditComments[0] || reviewComments[0] || null;
  const latestJob = ticketDetail?.job_history?.[0] || null;
  const filesChanged = Array.isArray(latestJob?.files_changed) ? latestJob.files_changed : [];
  const readOnlyRun = filesChanged.length === 0;

  const formatTimestamp = (value) => {
    if (!value) return "—";
    try {
      return new Date(value * 1000).toLocaleString();
    } catch (_err) {
      return "—";
    }
  };

  const statusBadgeClass = ticketDetail?.status ? (STATUS_COLORS[ticketDetail.status] || "bg-gray-100 text-gray-600") : "bg-gray-100 text-gray-600";

  return (
    <div className="space-y-6">
      {/* Statistics */}
      <TicketStats stats={stats} />
      
      {/* Filters */}
      <TicketFilters
        selectedMilestone={selectedMilestone}
        setSelectedMilestone={setSelectedMilestone}
        selectedSprint={selectedSprint}
        setSelectedSprint={setSelectedSprint}
        filterStatus={filterStatus}
        setFilterStatus={setFilterStatus}
        filterTool={filterTool}
        setFilterTool={setFilterTool}
        filterPriority={filterPriority}
        setFilterPriority={setFilterPriority}
        searchQuery={searchQuery}
        setSearchQuery={setSearchQuery}
        sortBy={sortBy}
        setSortBy={setSortBy}
        sortOrder={sortOrder}
        setSortOrder={setSortOrder}
        milestones={milestones}
        sprints={sprints}
      />
      
      {/* Bulk Operations */}
      <BulkOperations
        selectedTickets={selectedTickets}
        setSelectedTickets={setSelectedTickets}
        onRefresh={handleRefresh}
        tickets={filtered}
      />

      <div className="grid grid-cols-1 gap-6 xl:grid-cols-[minmax(0,2fr)_minmax(320px,1fr)]">
        {/* Ticket List */}
        <TicketList
          filtered={filtered}
          selectedTicket={selectedTicket}
          setSelectedTicket={setSelectedTicket}
          selectedTickets={selectedTickets}
          toggleTicketSelection={toggleTicketSelection}
          handleRefresh={handleRefresh}
          visibleSprints={visibleSprints}
        />

        {/* Review / audit trail */}
        <Card title="LLM review trail">
          {!selectedTicket ? (
            <p className="text-sm text-gray-500">
              Select a ticket to inspect LLM review notes, comment history, and execution snapshots.
            </p>
          ) : loadingDetail ? (
            <p className="text-sm text-gray-500">Loading ticket details…</p>
          ) : detailError ? (
            <div className="rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700">
              {detailError}
            </div>
          ) : ticketDetail ? (
            <div className="space-y-4">
              <div className="flex items-start justify-between gap-3">
                <div className="min-w-0">
                  <div className="flex flex-wrap items-center gap-2">
                    <h4 className="truncate text-sm font-semibold text-gray-900">{ticketDetail.title || ticketDetail.task || ticketDetail.id}</h4>
                    <span className={`text-xs px-2 py-0.5 rounded-full ${statusBadgeClass}`}>
                      {String(ticketDetail.status || "unknown").replaceAll("_", " ")}
                    </span>
                    <span className={`text-xs px-2 py-0.5 rounded-full ${PRIORITY_COLORS[ticketDetail.priority] || PRIORITY_COLORS.medium}`}>
                      {ticketDetail.priority || "medium"}
                    </span>
                  </div>
                  <p className="mt-1 text-xs font-mono text-gray-400">{ticketDetail.id}</p>
                </div>
                <button
                  type="button"
                  onClick={handleRefresh}
                  className="rounded-lg border border-gray-200 bg-white px-3 py-1.5 text-xs font-medium text-gray-700 transition-colors hover:bg-gray-50"
                >
                  Refresh
                </button>
              </div>

              <div className="grid grid-cols-2 gap-3 text-xs">
                <div className="rounded-lg border border-gray-200 bg-gray-50 p-3">
                  <div className="text-gray-500">Assigned tool</div>
                  <div className="mt-1 font-medium text-gray-900">{ticketDetail.assigned_tool?.tool || "unassigned"}</div>
                </div>
                <div className="rounded-lg border border-gray-200 bg-gray-50 p-3">
                  <div className="text-gray-500">Comments</div>
                  <div className="mt-1 font-medium text-gray-900">{reviewComments.length}</div>
                </div>
                <div className="rounded-lg border border-gray-200 bg-gray-50 p-3">
                  <div className="text-gray-500">Job snapshots</div>
                  <div className="mt-1 font-medium text-gray-900">{ticketDetail.job_history?.length || 0}</div>
                </div>
                <div className="rounded-lg border border-gray-200 bg-gray-50 p-3">
                  <div className="text-gray-500">Last update</div>
                  <div className="mt-1 font-medium text-gray-900">{formatTimestamp(ticketDetail.updated_at)}</div>
                </div>
              </div>

              {latestComment && (
                <div className="rounded-lg border border-purple-200 bg-purple-50 p-3">
                  <div className="flex flex-wrap items-center gap-2 text-[11px] font-semibold uppercase tracking-wide text-purple-700">
                    <span>Latest audit comment</span>
                    <span className="rounded-full bg-white/80 px-2 py-0.5 text-purple-600">
                      {latestComment.author || "system"}
                    </span>
                  </div>
                  <p className="mt-2 whitespace-pre-wrap text-sm text-purple-950">
                    {latestComment.content}
                  </p>
                  <div className="mt-2 text-[11px] text-purple-700/80">
                    {formatTimestamp(latestComment.created_at)}
                  </div>
                </div>
              )}

              <div>
                <div className="mb-2 flex items-center justify-between gap-2">
                  <h4 className="text-xs font-semibold uppercase tracking-wide text-gray-500">Recent comments</h4>
                  <span className="text-[11px] text-gray-400">Newest first</span>
                </div>
                {reviewComments.length > 0 ? (
                  <div className="space-y-2">
                    {reviewComments.slice(0, 5).map((comment) => {
                      const author = String(comment.author || "unknown");
                      const isAudit = author.toLowerCase().includes("orchestrator") || author.toLowerCase().includes("system") || author.toLowerCase().includes("llm");
                      return (
                        <div key={comment.id} className={`rounded-lg border p-3 text-sm ${isAudit ? "border-purple-200 bg-purple-50" : "border-gray-200 bg-gray-50"}`}>
                          <div className="flex flex-wrap items-center justify-between gap-2 text-xs">
                            <span className="font-medium text-gray-700">{author}</span>
                            <span className="text-gray-400">{formatTimestamp(comment.created_at)}</span>
                          </div>
                          <p className="mt-2 whitespace-pre-wrap text-gray-800">{comment.content}</p>
                        </div>
                      );
                    })}
                  </div>
                ) : (
                  <p className="text-sm text-gray-500">No comments recorded yet.</p>
                )}
              </div>

              <div>
                <div className="mb-2 flex items-center justify-between gap-2">
                  <h4 className="text-xs font-semibold uppercase tracking-wide text-gray-500">Latest execution</h4>
                  <span className={`text-[11px] px-2 py-0.5 rounded-full ${JOB_STATUS_COLORS[latestJob?.status] || "bg-gray-100 text-gray-600"}`}>
                    {latestJob?.status || "unknown"}
                  </span>
                </div>
                {latestJob ? (
                  <div className="space-y-3 rounded-lg border border-gray-200 bg-gray-50 p-3 text-sm">
                    <div className="flex flex-wrap items-center gap-2 text-xs text-gray-600">
                      <span className="font-mono">{latestJob.job_id || "job"}</span>
                      <span>•</span>
                      <span>{latestJob.tool || "unknown tool"}</span>
                      <span>•</span>
                      <span>{latestJob.mode || "default"}</span>
                      <span>•</span>
                      <span>{latestJob.model || "default model"}</span>
                    </div>

                    <div className="grid grid-cols-2 gap-2 text-xs text-gray-600">
                      <div><span className="text-gray-400">Duration:</span> {typeof latestJob.duration_s === "number" ? `${latestJob.duration_s.toFixed(2)}s` : "—"}</div>
                      <div><span className="text-gray-400">Exit code:</span> {latestJob.exit_code ?? "—"}</div>
                    </div>

                    <div className="rounded border border-gray-200 bg-white p-2 text-xs text-gray-700">
                      {readOnlyRun ? (
                        <p>
                          No files changed in the last execution. That is fine for read-only analysis,
                          review, or validation tasks and should not be treated as a failure on its own.
                        </p>
                      ) : (
                        <p>
                          {filesChanged.length} files changed in the last execution.
                        </p>
                      )}
                      {filesChanged.length > 0 && (
                        <div className="mt-2 flex flex-wrap gap-1">
                          {filesChanged.slice(0, 8).map((filePath) => (
                            <span key={filePath} className="rounded bg-gray-100 px-2 py-0.5 font-mono text-[11px] text-gray-600">
                              {filePath}
                            </span>
                          ))}
                        </div>
                      )}
                    </div>

                    {latestJob.error && (
                      <div className="rounded border border-red-200 bg-red-50 p-2 text-xs text-red-700">
                        {latestJob.error}
                      </div>
                    )}

                    {(latestJob.stdout_tail || latestJob.stderr_tail) && (
                      <div>
                        <div className="mb-1 text-[11px] font-semibold uppercase tracking-wide text-gray-500">
                          {latestJob.stderr_tail ? "Stdout / stderr tail" : "Stdout tail"}
                        </div>
                        <pre className="max-h-40 overflow-auto whitespace-pre-wrap rounded border border-gray-200 bg-white p-2 text-[11px] text-gray-700">
                          {latestJob.stdout_tail || latestJob.stderr_tail}
                        </pre>
                      </div>
                    )}
                  </div>
                ) : (
                  <p className="text-sm text-gray-500">No execution history available for this ticket yet.</p>
                )}
              </div>
            </div>
          ) : (
            <p className="text-sm text-gray-500">Unable to load ticket details.</p>
          )}
        </Card>
      </div>
    </div>
  );
}

export default TicketsPanelRefactored;
