import React, { useState } from 'react';
import styled from 'styled-components';
import { HiDocument, HiDownload, HiPhotograph } from 'react-icons/hi';
import { useLocale } from '@/app/providers/LocaleProvider';
import { Spinner } from '@/shared/components/ui';
import type { TicketAttachment } from '@/features/tickets/types/ticket.types';
import { resolveAttachmentPreviewUrl } from '@/shared/utils/attachmentUrl';
import { downloadAttachmentFile } from '@/shared/utils/fetchAttachment';

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

const AttachmentCard = styled.button`
  display: flex;
  align-items: center;
  gap: ${({ theme }) => theme.spacing[3]};
  width: 100%;
  padding: ${({ theme }) => theme.spacing[3]} ${({ theme }) => theme.spacing[4]};
  border-radius: ${({ theme }) => theme.borderRadius.md};
  border: 1px solid ${({ theme }) => theme.colors.border};
  background-color: ${({ theme }) => theme.colors.surface};
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  text-align: inherit;
  font: inherit;
  transition:
    box-shadow ${({ theme }) => theme.transitions.fast},
    border-color ${({ theme }) => theme.transitions.fast};

  &:hover:not(:disabled) {
    border-color: ${({ theme }) => theme.colors.borderStrong};
    box-shadow: ${({ theme }) => theme.shadows.xs};
  }

  &:disabled {
    cursor: wait;
    opacity: 0.7;
  }

  &:focus-visible {
    outline: 2px solid ${({ theme }) => theme.colors.primary};
    outline-offset: 2px;
  }
`;

const IconBox = styled.span`
  width: 40px;
  height: 40px;
  border-radius: ${({ theme }) => theme.borderRadius.md};
  background-color: ${({ theme }) => theme.colors.primaryLight};
  color: ${({ theme }) => theme.colors.primary};
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;

  svg {
    width: 20px;
    height: 20px;
  }
`;

const FileInfo = styled.div`
  flex: 1;
  min-width: 0;
  text-align: start;
`;

const FileName = styled.span`
  display: block;
  font-size: ${({ theme }) => theme.typography.fontSize.sm};
  font-weight: ${({ theme }) => theme.typography.fontWeight.medium};
  color: ${({ theme }) => theme.colors.text.primary};
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
`;

const FileSize = styled.span`
  font-size: ${({ theme }) => theme.typography.fontSize.xs};
  color: ${({ theme }) => theme.colors.text.tertiary};
`;

const DownloadIcon = styled.span`
  color: ${({ theme }) => theme.colors.text.tertiary};
  flex-shrink: 0;

  svg {
    width: 18px;
    height: 18px;
  }
`;

const Preview = styled.img`
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 320px;
  object-fit: contain;
  border-radius: ${({ theme }) => theme.borderRadius.md};
  margin-top: ${({ theme }) => theme.spacing[2]};
  border: 1px solid ${({ theme }) => theme.colors.border};
`;

const Message = styled.div`
  margin: 0;
  display: flex;
  align-items: center;
  gap: ${({ theme }) => theme.spacing[2]};
  color: ${({ theme }) => theme.colors.text.secondary};
  font-size: ${({ theme }) => theme.typography.fontSize.sm};
  text-align: start;
`;

function isImageMime(mime: string): boolean {
  return mime.startsWith('image/');
}

function fileIcon(mime: string) {
  return isImageMime(mime) ? <HiPhotograph /> : <HiDocument />;
}

function formatSize(
  bytes: number,
  formatted: string | undefined,
  t: (key: string, options?: Record<string, unknown>) => string,
): string {
  if (formatted) {
    return formatted;
  }
  if (bytes < 1024) {
    return t('tickets:fileSize.bytes', { size: bytes });
  }
  if (bytes < 1024 * 1024) {
    return t('tickets:fileSize.kilobytes', { size: (bytes / 1024).toFixed(1) });
  }
  return t('tickets:fileSize.megabytes', { size: (bytes / (1024 * 1024)).toFixed(1) });
}

interface AttachmentsListProps {
  attachments?: TicketAttachment[];
  isLoading?: boolean;
  isError?: boolean;
  emptyLabel: string;
  errorLabel: string;
}

export const AttachmentsList: React.FC<AttachmentsListProps> = ({
  attachments = [],
  isLoading = false,
  isError = false,
  emptyLabel,
  errorLabel,
}) => {
  const { t } = useLocale();
  const [downloadingId, setDownloadingId] = useState<string | null>(null);

  if (isLoading) {
    return (
      <Message role="status">
        <Spinner size="sm" /> {t('tickets:attachmentsStates.loading')}
      </Message>
    );
  }

  if (isError) {
    return <Message role="alert">{errorLabel}</Message>;
  }

  if (attachments.length === 0) {
    return <Message>{emptyLabel}</Message>;
  }

  return (
    <Grid>
      {attachments.map((attachment) => {
        const previewSrc = resolveAttachmentPreviewUrl(attachment);
        const showPreview = isImageMime(attachment.mime_type);

        return (
          <div key={attachment.id}>
            <AttachmentCard
              type="button"
              disabled={downloadingId !== null}
              aria-label={attachment.file_name}
              onClick={async () => {
                setDownloadingId(attachment.id);
                try {
                  await downloadAttachmentFile(attachment);
                } finally {
                  setDownloadingId(null);
                }
              }}
            >
              <IconBox aria-hidden>{fileIcon(attachment.mime_type)}</IconBox>
              <FileInfo>
                <FileName>{attachment.file_name}</FileName>
                <FileSize>
                  {formatSize(attachment.file_size, attachment.formatted_size, t)}
                </FileSize>
              </FileInfo>
              <DownloadIcon aria-hidden>
                <HiDownload />
              </DownloadIcon>
            </AttachmentCard>
            {showPreview && (
              <Preview
                src={previewSrc}
                alt={attachment.file_name}
                loading="lazy"
              />
            )}
          </div>
        );
      })}
    </Grid>
  );
};
