import React, { useMemo, useState } from 'react';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { HiOutlineLink, HiOutlineTrash } from 'react-icons/hi';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useLocale } from '@/app/providers/LocaleProvider';
import { Badge, Button, Card, IconButton, Select, Spinner, StatusBadge } from '@/shared/components/ui';
import { PanelEmpty } from '@/shared/components/ui/PageState';
import { ROUTES } from '@/shared/constants/routes';
import type { DependencyType } from '@/features/projects/types/project.types';
import {
  DEPENDENCY_TYPES,
  getDependencyTypeLabel,
  getDependencyTypeTooltip,
} from '@/features/tickets/constants/dependencyTypes';
import { TicketDependencySearchPicker } from '@/features/tickets/components/TicketDependencySearchPicker';
import {
  addBlocksDependency,
  addDependsOnDependency,
  fetchTicketDependencies,
  removeTicketDependency,
  type TicketDependencyRecord,
  type TicketDependencySearchHit,
} from '@/features/tickets/services/ticketDependencyService';

const SummaryRow = styled.div`
  display: flex;
  flex-wrap: wrap;
  gap: ${({ theme }) => theme.spacing[2]};
  margin-bottom: ${({ theme }) => theme.spacing[5]};
`;

const WarningBanner = styled.p`
  margin: 0 0 ${({ theme }) => theme.spacing[4]};
  padding: ${({ theme }) => theme.spacing[3]} ${({ theme }) => theme.spacing[4]};
  border-radius: ${({ theme }) => theme.borderRadius.sm};
  background: ${({ theme }) => theme.colors.warningLight};
  color: ${({ theme }) => theme.colors.text.primary};
  font-size: ${({ theme }) => theme.typography.fontSize.sm};
  line-height: ${({ theme }) => theme.typography.lineHeight.relaxed};
`;

const Groups = styled.div`
  display: flex;
  flex-direction: column;
  gap: ${({ theme }) => theme.spacing[6]};
`;

const Group = styled.section`
  display: flex;
  flex-direction: column;
  gap: ${({ theme }) => theme.spacing[4]};
`;

const GroupHeader = styled.div`
  display: flex;
  flex-direction: column;
  gap: ${({ theme }) => theme.spacing[1]};
`;

const GroupTitle = styled.h4`
  margin: 0;
  font-size: ${({ theme }) => theme.typography.fontSize.sm};
  font-weight: ${({ theme }) => theme.typography.fontWeight.semibold};
  color: ${({ theme }) => theme.colors.text.primary};
`;

const GroupDescription = styled.p`
  margin: 0;
  font-size: ${({ theme }) => theme.typography.fontSize.xs};
  color: ${({ theme }) => theme.colors.text.secondary};
  line-height: ${({ theme }) => theme.typography.lineHeight.relaxed};
`;

const CardGrid = styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  gap: ${({ theme }) => theme.spacing[3]};
`;

const DependencyCard = styled.article`
  display: flex;
  flex-direction: column;
  gap: ${({ theme }) => theme.spacing[3]};
  padding: ${({ theme }) => theme.spacing[4]};
  border-radius: ${({ theme }) => theme.borderRadius.md};
  border: 1px solid ${({ theme }) => theme.colors.borderSoft};
  background: ${({ theme }) => theme.colors.surface};
  min-width: 0;
`;

const CardTop = styled.div`
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: ${({ theme }) => theme.spacing[2]};
`;

const TicketLink = styled(Link)`
  display: flex;
  flex-direction: column;
  gap: ${({ theme }) => theme.spacing[1]};
  min-width: 0;
  text-decoration: none;
  color: inherit;

  &:hover strong {
    color: ${({ theme }) => theme.colors.primary};
  }
`;

const TicketKey = styled.strong`
  font-size: ${({ theme }) => theme.typography.fontSize.sm};
  font-weight: ${({ theme }) => theme.typography.fontWeight.semibold};
  color: ${({ theme }) => theme.colors.text.primary};
`;

const TicketTitle = styled.span`
  font-size: ${({ theme }) => theme.typography.fontSize.sm};
  color: ${({ theme }) => theme.colors.text.secondary};
  line-height: ${({ theme }) => theme.typography.lineHeight.relaxed};
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
`;

const CardMeta = styled.div`
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: ${({ theme }) => theme.spacing[2]};
`;

const TypeBadge = styled.span`
  display: inline-flex;
  align-items: center;
  padding: 0.125rem ${({ theme }) => theme.spacing[2]};
  border-radius: ${({ theme }) => theme.borderRadius.full};
  font-size: ${({ theme }) => theme.typography.fontSize.xs};
  font-weight: ${({ theme }) => theme.typography.fontWeight.medium};
  background: ${({ theme }) => theme.colors.surfaceInset};
  border: 1px solid ${({ theme }) => theme.colors.borderSoft};
  color: ${({ theme }) => theme.colors.text.secondary};
  cursor: help;
`;

const GroupEmpty = styled.p`
  margin: 0;
  padding: ${({ theme }) => theme.spacing[4]};
  border-radius: ${({ theme }) => theme.borderRadius.sm};
  border: 1px dashed ${({ theme }) => theme.colors.borderSoft};
  font-size: ${({ theme }) => theme.typography.fontSize.sm};
  color: ${({ theme }) => theme.colors.text.tertiary};
  text-align: center;
`;

const AddForm = styled.div`
  display: flex;
  flex-direction: column;
  gap: ${({ theme }) => theme.spacing[3]};
  padding: ${({ theme }) => theme.spacing[4]};
  border-radius: ${({ theme }) => theme.borderRadius.md};
  border: 1px solid ${({ theme }) => theme.colors.borderSoft};
  background: ${({ theme }) => theme.colors.surfaceInset};

  @media (min-width: 640px) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(140px, 180px) auto;
    align-items: end;
  }
`;

const LoadingWrap = styled.div`
  display: flex;
  justify-content: center;
  padding: ${({ theme }) => theme.spacing[8]};
`;

type DependencyGroup = 'dependsOn' | 'blocks';

interface Props {
  ticketId: string;
  readOnly?: boolean;
  variant?: 'card' | 'panel';
}

const DependencyCardItem: React.FC<{
  record: TicketDependencyRecord;
  readOnly: boolean;
  onRemove: (dependencyId: string) => void;
  removing: boolean;
  statusOpenLabel: string;
  statusDoneLabel: string;
  removeLabel: string;
}> = ({ record, readOnly, onRemove, removing, statusOpenLabel, statusDoneLabel, removeLabel }) => {
  const ticket = record.ticket;
  if (!ticket) {
    return null;
  }

  const statusLabel = ticket.status?.name_en ?? (ticket.is_done ? statusDoneLabel : statusOpenLabel);
  const statusTone = ticket.is_done ? 'success' : 'open';

  return (
    <DependencyCard>
      <CardTop>
        <TicketLink to={ROUTES.TICKET_DETAIL(ticket.id)}>
          <TicketKey>{ticket.ticket_number}</TicketKey>
          <TicketTitle>{ticket.subject}</TicketTitle>
        </TicketLink>
        {!readOnly && (
          <IconButton
            size="sm"
            tone="danger"
            label={removeLabel}
            onClick={() => onRemove(record.id)}
            disabled={removing}
          >
            <HiOutlineTrash aria-hidden />
          </IconButton>
        )}
      </CardTop>
      <CardMeta>
        <TypeBadge title={getDependencyTypeTooltip(record.dependency_type)}>
          {getDependencyTypeLabel(record.dependency_type)}
        </TypeBadge>
        <StatusBadge tone={statusTone} size="sm" dot>
          {statusLabel}
        </StatusBadge>
      </CardMeta>
    </DependencyCard>
  );
};

export const TicketDependenciesPanel: React.FC<Props> = ({
  ticketId,
  readOnly = false,
  variant = 'card',
}) => {
  const { t } = useLocale();
  const queryClient = useQueryClient();
  const [dependsOnPick, setDependsOnPick] = useState<TicketDependencySearchHit | null>(null);
  const [blocksPick, setBlocksPick] = useState<TicketDependencySearchHit | null>(null);
  const [dependsOnType, setDependsOnType] = useState<DependencyType>('FS');
  const [blocksType, setBlocksType] = useState<DependencyType>('FS');

  const queryKey = ['tickets', ticketId, 'dependencies'];

  const depsQuery = useQuery({
    queryKey,
    queryFn: () => fetchTicketDependencies(ticketId),
  });

  const invalidate = () => {
    void queryClient.invalidateQueries({ queryKey });
  };

  const removeMutation = useMutation({
    mutationFn: (dependencyId: string) => removeTicketDependency(ticketId, dependencyId),
    onSuccess: invalidate,
  });

  const addDependsOnMutation = useMutation({
    mutationFn: () => addDependsOnDependency(ticketId, dependsOnPick!.id, dependsOnType),
    onSuccess: () => {
      setDependsOnPick(null);
      invalidate();
    },
  });

  const addBlocksMutation = useMutation({
    mutationFn: () => addBlocksDependency(ticketId, blocksPick!.id, blocksType),
    onSuccess: () => {
      setBlocksPick(null);
      invalidate();
    },
  });

  const blockedBy = depsQuery.data?.blocked_by ?? [];
  const blocking = depsQuery.data?.blocking ?? [];
  const warnings = depsQuery.data?.warnings ?? [];

  const totalCount = blockedBy.length + blocking.length;

  const typeOptions = useMemo(
    () =>
      DEPENDENCY_TYPES.map((type) => ({
        value: type,
        label: getDependencyTypeLabel(type),
      })),
    [],
  );

  const renderAddForm = (group: DependencyGroup) => {
    const isDependsOn = group === 'dependsOn';
    const pick = isDependsOn ? dependsOnPick : blocksPick;
    const depType = isDependsOn ? dependsOnType : blocksType;
    const setPick = isDependsOn ? setDependsOnPick : setBlocksPick;
    const setDepType = isDependsOn ? setDependsOnType : setBlocksType;
    const mutation = isDependsOn ? addDependsOnMutation : addBlocksMutation;

    return (
      <AddForm>
        <TicketDependencySearchPicker
          ticketId={ticketId}
          value={pick}
          onChange={setPick}
          placeholder={t('tickets:dependencies.searchPlaceholder')}
          loadingLabel={t('tickets:dependencies.searchLoading')}
          errorLabel={t('tickets:dependencies.searchError')}
          emptyLabel={t('tickets:dependencies.searchEmpty')}
        />
        <Select
          label={t('tickets:dependencies.typeLabel')}
          value={depType}
          onChange={(event) => setDepType(event.target.value as DependencyType)}
          options={typeOptions}
          hint={getDependencyTypeTooltip(depType)}
          fullWidth
        />
        <Button
          type="button"
          variant="primary"
          size="lg"
          disabled={!pick}
          loading={mutation.isPending}
          onClick={() => mutation.mutate()}
        >
          {t('tickets:dependencies.addLink')}
        </Button>
      </AddForm>
    );
  };

  const content = (
    <>
      <SummaryRow aria-label={t('tickets:dependencies.summaryLabel')}>
        <Badge variant="gray" size="sm">
          {t('tickets:dependencies.summaryTotal', { count: totalCount })}
        </Badge>
        <Badge variant="warning" size="sm">
          {t('tickets:dependencies.summaryBlockedBy', { count: blockedBy.length })}
        </Badge>
        <Badge variant="info" size="sm">
          {t('tickets:dependencies.summaryBlocking', { count: blocking.length })}
        </Badge>
      </SummaryRow>

      {warnings.length > 0 && (
        <WarningBanner role="status">
          {t('tickets:dependencies.openBlockersWarning', { count: warnings.length })}
        </WarningBanner>
      )}

      {depsQuery.isLoading && (
        <LoadingWrap>
          <Spinner />
        </LoadingWrap>
      )}

      {!depsQuery.isLoading && totalCount === 0 && (
        <PanelEmpty
          icon={<HiOutlineLink aria-hidden />}
          title={t('tickets:dependencies.empty')}
        />
      )}

      {!depsQuery.isLoading && (
        <Groups>
          <Group aria-labelledby="depends-on-heading">
            <GroupHeader>
              <GroupTitle id="depends-on-heading">{t('tickets:dependencies.dependsOn')}</GroupTitle>
              <GroupDescription>{t('tickets:dependencies.dependsOnDescription')}</GroupDescription>
            </GroupHeader>

            {blockedBy.length > 0 ? (
              <CardGrid>
                {blockedBy.map((record) => (
                  <DependencyCardItem
                    key={record.id}
                    record={record}
                    readOnly={readOnly}
                    onRemove={(id) => removeMutation.mutate(id)}
                    removing={removeMutation.isPending}
                    statusOpenLabel={t('tickets:dependencies.statusOpen')}
                    statusDoneLabel={t('tickets:dependencies.statusDone')}
                    removeLabel={t('tickets:dependencies.remove')}
                  />
                ))}
              </CardGrid>
            ) : totalCount > 0 ? (
              <GroupEmpty>{t('tickets:dependencies.groupEmptyDependsOn')}</GroupEmpty>
            ) : null}

            {!readOnly && renderAddForm('dependsOn')}
          </Group>

          <Group aria-labelledby="blocks-heading">
            <GroupHeader>
              <GroupTitle id="blocks-heading">{t('tickets:dependencies.blocks')}</GroupTitle>
              <GroupDescription>{t('tickets:dependencies.blocksDescription')}</GroupDescription>
            </GroupHeader>

            {blocking.length > 0 ? (
              <CardGrid>
                {blocking.map((record) => (
                  <DependencyCardItem
                    key={record.id}
                    record={record}
                    readOnly={readOnly}
                    onRemove={(id) => removeMutation.mutate(id)}
                    removing={removeMutation.isPending}
                    statusOpenLabel={t('tickets:dependencies.statusOpen')}
                    statusDoneLabel={t('tickets:dependencies.statusDone')}
                    removeLabel={t('tickets:dependencies.remove')}
                  />
                ))}
              </CardGrid>
            ) : totalCount > 0 ? (
              <GroupEmpty>{t('tickets:dependencies.groupEmptyBlocks')}</GroupEmpty>
            ) : null}

            {!readOnly && renderAddForm('blocks')}
          </Group>
        </Groups>
      )}
    </>
  );

  if (variant === 'panel') {
    return content;
  }

  return (
    <Card variant="muted" padding="lg" header={t('tickets:dependencies.title')}>
      {content}
    </Card>
  );
};
