'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';
import { X } from 'lucide-react';

import { MultiSelectPopover } from '@/components/form/MultiSelectPopover';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';

import {
  useDetectionCoordinatesQuery,
  useTicketDetectionsQuery,
} from '../../../hooks/useTicketQueries';
import {
  formatCompactRangeCoordinate,
  formatRangeCoordinate,
  type AssignmentRangePoint,
} from './assignmentRange';
import { AssignmentIssuesMap } from './AssignmentIssuesMap';
import { useIssueColumns } from './IssueColumns';
import { IssueTable } from './IssueTable';

const DEFAULT_PAGE_SIZE = 10;
const MAP_PAGE_SIZE = 50;

interface IssueTypeOption {
  class_name: string;
  display_name: string;
  count: number;
}

interface ChooseIssuesSectionProps {
  videoId?: string;
  issueTypes: IssueTypeOption[];
  selectedIssueTypes: string[];
  startPoint: AssignmentRangePoint | null;
  endPoint: AssignmentRangePoint | null;
  onSelectedIssueTypesChange: (values: string[]) => void;
  onStartPointChange: (point: AssignmentRangePoint | null) => void;
  onEndPointChange: (point: AssignmentRangePoint | null) => void;
}

export function ChooseIssuesSection({
  videoId,
  issueTypes,
  selectedIssueTypes,
  startPoint,
  endPoint,
  onSelectedIssueTypesChange,
  onStartPointChange,
  onEndPointChange,
}: ChooseIssuesSectionProps) {
  const [skip, setSkip] = useState(0);
  const [limit, setLimit] = useState(DEFAULT_PAGE_SIZE);
  const handleSetStart = useCallback(
    (point: AssignmentRangePoint) => {
      onStartPointChange(point);
      onEndPointChange(null);
    },
    [onEndPointChange, onStartPointChange],
  );
  const handleSetEnd = useCallback(
    (point: AssignmentRangePoint) => {
      if (point.detectionId === startPoint?.detectionId) return;

      onEndPointChange(point);
    },
    [onEndPointChange, startPoint?.detectionId],
  );
  const columns = useIssueColumns({
    startPoint,
    endPoint,
    onSetStart: handleSetStart,
    onSetEnd: handleSetEnd,
  });
  const issueTypeOptions = useMemo(
    () =>
      issueTypes.map((issue) => ({
        value: issue.class_name,
        label: issue.display_name,
      })),
    [issueTypes],
  );
  const handleIssueTypesChange = useCallback(
    (values: string[]) => {
      onSelectedIssueTypesChange(values);
      onStartPointChange(null);
      onEndPointChange(null);
    },
    [onEndPointChange, onSelectedIssueTypesChange, onStartPointChange],
  );
  useEffect(() => {
    setSkip(0);
  }, [selectedIssueTypes]);

  const queryParams = useMemo(
    () => ({
      skip,
      limit,
      class_name:
        selectedIssueTypes.length > 0 ? selectedIssueTypes : undefined,
      sort: 'timestamp_asc',
    }),
    [limit, selectedIssueTypes, skip],
  );
  const detectionsQuery = useTicketDetectionsQuery(videoId, queryParams);
  const mapQueryParams = useMemo(
    () => ({
      limit: MAP_PAGE_SIZE,
      class_name:
        selectedIssueTypes.length > 0 ? selectedIssueTypes : undefined,
      assignment_status: 'unassigned' as const,
    }),
    [selectedIssueTypes],
  );
  const coordinatesQuery = useDetectionCoordinatesQuery(
    videoId,
    mapQueryParams,
  );
  const result = detectionsQuery.data;
  const mapData = useMemo(() => {
    const pages = coordinatesQuery.data?.pages;

    if (!pages?.length) return undefined;

    const latestPage = pages[pages.length - 1];

    return {
      ...latestPage,
      items: pages.flatMap((page) => page.items),
      truncated: Boolean(coordinatesQuery.hasNextPage),
    };
  }, [coordinatesQuery.data?.pages, coordinatesQuery.hasNextPage]);

  return (
    <div className="min-w-0 space-y-5">
      <Card size="sm" aria-label="Issue filters">
        <CardHeader>
          <CardTitle>Filters</CardTitle>
        </CardHeader>
        <CardContent>
          <div className="flex flex-wrap items-center gap-2">
            <MultiSelectPopover
              label="Issue Types"
              options={issueTypeOptions}
              values={selectedIssueTypes}
              onValuesChange={handleIssueTypesChange}
              searchPlaceholder="Search issue types"
              emptyMessage="No issue types found."
              emptySelectionLabel="All"
              align="start"
            />

            {startPoint ? (
              <Badge
                variant="outline"
                className="h-8 gap-1.5 px-2.5 font-normal"
                title={formatRangeCoordinate(startPoint)}
              >
                <span className="font-medium">Start</span>
                <span className="font-mono">
                  {formatCompactRangeCoordinate(startPoint)}
                </span>
              </Badge>
            ) : null}

            {endPoint ? (
              <Badge
                variant="outline"
                className="h-8 gap-1.5 px-2.5 font-normal"
                title={formatRangeCoordinate(endPoint)}
              >
                <span className="font-medium">End</span>
                <span className="font-mono">
                  {formatCompactRangeCoordinate(endPoint)}
                </span>
              </Badge>
            ) : null}

            {startPoint !== null || endPoint !== null ? (
              <Button
                type="button"
                variant="ghost"
                size="icon"
                className="size-8"
                aria-label="Clear coordinate range"
                onClick={() => {
                  onStartPointChange(null);
                  onEndPointChange(null);
                }}
              >
                <X />
              </Button>
            ) : null}
          </div>
        </CardContent>
      </Card>

      <AssignmentIssuesMap
        data={mapData}
        isLoading={coordinatesQuery.isLoading}
        isFetchingMore={coordinatesQuery.isFetchingNextPage}
        isError={coordinatesQuery.isError}
        hasMore={Boolean(coordinatesQuery.hasNextPage)}
        startPoint={startPoint}
        endPoint={endPoint}
        onSetStart={handleSetStart}
        onSetEnd={handleSetEnd}
        onLoadMore={() => void coordinatesQuery.fetchNextPage()}
        onRetry={() => void coordinatesQuery.refetch()}
      />

      <IssueTable
        columns={columns}
        issues={result?.items ?? []}
        isLoading={detectionsQuery.isLoading}
        isError={detectionsQuery.isError}
        toolbar={null}
        skip={skip}
        limit={limit}
        total={result?.total ?? 0}
        onPageChange={setSkip}
        onLimitChange={setLimit}
      />
    </div>
  );
}
