'use client';

import { Check } from 'lucide-react';
import { useState, useCallback, useEffect } from 'react';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Select } from '@/components/ui/select';
import { useAuthStore } from '@/lib/auth-store';

const KYC_STATUS_MAP: Record<string, { label: string; variant: 'default' | 'secondary' | 'destructive' | 'outline'; description: string }> = {
  NONE: { label: 'Chưa xác minh', variant: 'outline', description: 'Bạn chưa gửi hồ sơ xác minh danh tính. Hoàn tất KYC để mở khóa đầy đủ tính năng.' },
  PENDING: { label: 'Đang chờ duyệt', variant: 'secondary', description: 'Hồ sơ của bạn đã được gửi và đang chờ đội ngũ quản trị xem xét. Vui lòng chờ 1-3 ngày làm việc.' },
  VERIFIED: { label: 'Đã xác minh', variant: 'default', description: 'Danh tính của bạn đã được xác minh thành công. Bạn có thể sử dụng đầy đủ tính năng.' },
  REJECTED: { label: 'Bị từ chối', variant: 'destructive', description: 'Hồ sơ xác minh bị từ chối. Vui lòng kiểm tra lại và gửi lại hồ sơ.' },
};

const DOCUMENT_TYPES = [
  { value: 'CCCD', label: 'Căn cước công dân (CCCD)' },
  { value: 'CMND', label: 'Chứng minh nhân dân (CMND)' },
  { value: 'PASSPORT', label: 'Hộ chiếu' },
  { value: 'BUSINESS_LICENSE', label: 'Giấy phép kinh doanh' },
];

const KYC_STEPS = [
  { step: 1, title: 'Loại giấy tờ', description: 'Chọn loại giấy tờ tùy thân' },
  { step: 2, title: 'Tải ảnh', description: 'Tải ảnh mặt trước, mặt sau và ảnh selfie' },
  { step: 3, title: 'Xác nhận', description: 'Kiểm tra và gửi hồ sơ' },
];

const API_BASE_URL =
  process.env['NEXT_PUBLIC_API_URL'] || 'http://localhost:3001/api/v1';

const MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024; // 5MB
const ACCEPTED_MIME_TYPES = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp', 'application/pdf'];
const ACCEPTED_ACCEPT_ATTR = 'image/jpeg,image/png,image/webp,application/pdf';

function validateFile(file: File): string | null {
  if (!ACCEPTED_MIME_TYPES.includes(file.type)) {
    return 'Định dạng không hợp lệ. Vui lòng chọn JPG, PNG, WEBP hoặc PDF.';
  }
  if (file.size > MAX_FILE_SIZE_BYTES) {
    return 'Kích thước tệp vượt quá 5MB. Vui lòng chọn tệp nhỏ hơn.';
  }
  return null;
}

function getCsrfToken(): string | undefined {
  const csrfMatch = document.cookie.match(/(?:^|;\s*)XSRF-TOKEN=([^;]*)/);
  return csrfMatch?.[1] ? decodeURIComponent(csrfMatch[1]) : undefined;
}

function buildHeaders(): Record<string, string> {
  const headers: Record<string, string> = { 'Content-Type': 'application/json' };
  const csrfToken = getCsrfToken();
  if (csrfToken) headers['X-CSRF-Token'] = csrfToken;
  return headers;
}

interface PresignedUrlResult {
  field: string;
  uploadUrl: string;
  publicUrl: string;
  objectKey: string;
}

function uploadFileWithProgress(
  url: string,
  file: File,
  onProgress: (percent: number) => void,
): Promise<void> {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('PUT', url);
    xhr.setRequestHeader('Content-Type', file.type);

    xhr.upload.addEventListener('progress', (e) => {
      if (e.lengthComputable) {
        onProgress(Math.round((e.loaded / e.total) * 100));
      }
    });

    xhr.addEventListener('load', () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        onProgress(100);
        resolve();
      } else if (xhr.status === 403) {
        reject(new Error('Liên kết tải lên đã hết hạn. Vui lòng thử lại.'));
      } else {
        reject(new Error(`Tải ảnh thất bại (${xhr.status}). Vui lòng thử lại.`));
      }
    });

    xhr.addEventListener('error', () => reject(new Error('Lỗi kết nối khi tải ảnh')));
    xhr.addEventListener('abort', () => reject(new Error('Tải ảnh đã bị hủy')));

    xhr.send(file);
  });
}

export default function KycPage() {
  const { user, fetchProfile } = useAuthStore();
  const [currentStep, setCurrentStep] = useState(1);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState(false);
  const [uploadProgress, setUploadProgress] = useState<Record<string, number>>({});

  const [documentType, setDocumentType] = useState('CCCD');
  const [documentNumber, setDocumentNumber] = useState('');
  const [frontImage, setFrontImage] = useState<File | null>(null);
  const [backImage, setBackImage] = useState<File | null>(null);
  const [selfieImage, setSelfieImage] = useState<File | null>(null);
  const [frontPreview, setFrontPreview] = useState<string | null>(null);
  const [backPreview, setBackPreview] = useState<string | null>(null);
  const [selfiePreview, setSelfiePreview] = useState<string | null>(null);

  // Revoke object URLs on cleanup to avoid memory leaks
  useEffect(() => {
    return () => {
      if (frontPreview) URL.revokeObjectURL(frontPreview);
      if (backPreview) URL.revokeObjectURL(backPreview);
      if (selfiePreview) URL.revokeObjectURL(selfiePreview);
    };
  }, [frontPreview, backPreview, selfiePreview]);

  const handleFileSelect = useCallback(
    (
      field: 'front' | 'back' | 'selfie',
      file: File | null,
    ) => {
      if (!file) return;
      const validationError = validateFile(file);
      if (validationError) {
        setError(validationError);
        return;
      }
      setError(null);
      const previewUrl = file.type.startsWith('image/') ? URL.createObjectURL(file) : null;
      if (field === 'front') {
        if (frontPreview) URL.revokeObjectURL(frontPreview);
        setFrontImage(file);
        setFrontPreview(previewUrl);
      } else if (field === 'back') {
        if (backPreview) URL.revokeObjectURL(backPreview);
        setBackImage(file);
        setBackPreview(previewUrl);
      } else {
        if (selfiePreview) URL.revokeObjectURL(selfiePreview);
        setSelfieImage(file);
        setSelfiePreview(previewUrl);
      }
    },
    [frontPreview, backPreview, selfiePreview],
  );

  const kycStatus = user?.kycStatus ?? 'NONE';
  const kycInfo = KYC_STATUS_MAP[kycStatus] ?? { label: 'Chưa xác minh', variant: 'outline' as const, description: 'Bạn chưa gửi hồ sơ xác minh danh tính.' };
  const canSubmit = kycStatus === 'NONE' || kycStatus === 'REJECTED';

  const totalProgress = useCallback(() => {
    const fields = Object.values(uploadProgress);
    if (fields.length === 0) return 0;
    return Math.round(fields.reduce((sum, p) => sum + p, 0) / fields.length);
  }, [uploadProgress]);

  const handleSubmit = async () => {
    if (!documentNumber.trim()) {
      setError('Vui lòng nhập số giấy tờ');
      return;
    }
    if (!frontImage) {
      setError('Vui lòng tải ảnh mặt trước');
      return;
    }

    setSubmitting(true);
    setError(null);
    setUploadProgress({});

    try {
      // Step 1: Build the list of files to upload
      const filesToUpload: { field: 'frontImage' | 'backImage' | 'selfieImage'; file: File }[] = [
        { field: 'frontImage', file: frontImage },
      ];
      if (backImage) filesToUpload.push({ field: 'backImage', file: backImage });
      if (selfieImage) filesToUpload.push({ field: 'selfieImage', file: selfieImage });

      // Step 2: Request presigned URLs from the backend
      const uploadUrlsRes = await fetch(`${API_BASE_URL}/auth/kyc/upload-urls`, {
        method: 'POST',
        credentials: 'include',
        headers: buildHeaders(),
        body: JSON.stringify({
          files: filesToUpload.map((f) => ({
            field: f.field,
            mimeType: f.file.type,
            fileName: f.file.name,
          })),
        }),
      });

      if (!uploadUrlsRes.ok) {
        const errData = await uploadUrlsRes.json().catch(() => ({ message: uploadUrlsRes.statusText }));
        throw new Error(errData.message || 'Không thể tạo URL tải lên');
      }

      const presignedUrls: PresignedUrlResult[] = await uploadUrlsRes.json();

      // Step 3: Upload each file directly to MinIO via presigned URL
      const urlMap = new Map(presignedUrls.map((p) => [p.field, p]));

      await Promise.all(
        filesToUpload.map(({ field, file }) => {
          const presigned = urlMap.get(field);
          if (!presigned) throw new Error(`Không tìm thấy URL tải lên cho ${field}`);

          return uploadFileWithProgress(presigned.uploadUrl, file, (percent) => {
            setUploadProgress((prev) => ({ ...prev, [field]: percent }));
          });
        }),
      );

      // Step 4: Submit KYC with the uploaded image URLs
      const frontUrl = urlMap.get('frontImage')!.publicUrl;
      const backUrl = urlMap.get('backImage')?.publicUrl;
      const selfieUrl = urlMap.get('selfieImage')?.publicUrl;

      const submitRes = await fetch(`${API_BASE_URL}/auth/kyc/submit`, {
        method: 'POST',
        credentials: 'include',
        headers: buildHeaders(),
        body: JSON.stringify({
          documentType,
          documentNumber: documentNumber.trim(),
          frontImageUrl: frontUrl,
          backImageUrl: backUrl,
          selfieUrl,
        }),
      });

      if (!submitRes.ok) {
        const errData = await submitRes.json().catch(() => ({ message: submitRes.statusText }));
        throw new Error(errData.message || 'Gửi hồ sơ thất bại');
      }

      await fetchProfile();
      setSuccess(true);
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Gửi hồ sơ thất bại');
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <div className="space-y-6" data-testid="kyc-page">
      <div>
        <h1 className="text-2xl font-bold sm:text-3xl">Xác minh danh tính (KYC)</h1>
        <p className="mt-2 text-muted-foreground">
          Xác minh danh tính để sử dụng đầy đủ tính năng của GoodGo
        </p>
      </div>

      {/* KYC Status */}
      <Card>
        <CardHeader>
          <div className="flex items-center justify-between">
            <CardTitle className="text-lg">Trạng thái xác minh</CardTitle>
            <Badge variant={kycInfo.variant}>{kycInfo.label}</Badge>
          </div>
        </CardHeader>
        <CardContent>
          <p className="text-sm text-muted-foreground">{kycInfo.description}</p>
        </CardContent>
      </Card>

      {error && (
        <div
          role="alert"
          data-testid="kyc-error"
          className="rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-700"
        >
          {error}
          <button onClick={() => setError(null)} className="ml-2 font-medium underline">
            Đóng
          </button>
        </div>
      )}

      {success && (
        <div
          role="status"
          data-testid="kyc-success"
          className="rounded-lg border border-green-200 bg-green-50 p-4 text-sm text-green-700"
        >
          Hồ sơ KYC đã được gửi thành công. Vui lòng chờ 1-3 ngày làm việc để được xem xét.
        </div>
      )}

      {/* KYC Form */}
      {canSubmit && !success && (
        <>
          {/* Step indicator */}
          <div className="flex items-center justify-center gap-2">
            {KYC_STEPS.map((s, i) => (
              <div key={s.step} className="flex items-center">
                <div
                  className={`flex h-8 w-8 items-center justify-center rounded-full text-sm font-semibold ${
                    currentStep >= s.step
                      ? 'bg-primary text-primary-foreground'
                      : 'bg-muted text-muted-foreground'
                  }`}
                >
                  {s.step}
                </div>
                <span className="ml-2 hidden text-sm sm:inline">{s.title}</span>
                {i < KYC_STEPS.length - 1 && (
                  <div className="mx-1 h-px w-4 bg-border sm:mx-3 sm:w-16" />
                )}
              </div>
            ))}
          </div>

          <Card>
            <CardHeader>
              <CardTitle className="text-lg">
                {KYC_STEPS[currentStep - 1]?.title}
              </CardTitle>
              <CardDescription>
                {KYC_STEPS[currentStep - 1]?.description}
              </CardDescription>
            </CardHeader>
            <CardContent className="space-y-4">
              {/* Step 1: Document type */}
              {currentStep === 1 && (
                <>
                  <div className="space-y-2">
                    <Label htmlFor="docType">Loại giấy tờ</Label>
                    <Select
                      id="docType"
                      value={documentType}
                      onChange={(e) => setDocumentType(e.target.value)}
                    >
                      {DOCUMENT_TYPES.map((dt) => (
                        <option key={dt.value} value={dt.value}>
                          {dt.label}
                        </option>
                      ))}
                    </Select>
                  </div>
                  <div className="space-y-2">
                    <Label htmlFor="docNumber">Số giấy tờ</Label>
                    <Input
                      id="docNumber"
                      value={documentNumber}
                      onChange={(e) => setDocumentNumber(e.target.value)}
                      placeholder="Nhập số CCCD/CMND/Hộ chiếu"
                    />
                  </div>
                </>
              )}

              {/* Step 2: Upload images */}
              {currentStep === 2 && (
                <>
                  <p className="text-xs text-muted-foreground">
                    Định dạng hỗ trợ: JPG, PNG, WEBP, PDF. Kích thước tối đa: 5MB.
                  </p>
                  <div className="space-y-2">
                    <Label htmlFor="frontImg">Ảnh mặt trước *</Label>
                    <Input
                      id="frontImg"
                      data-testid="kyc-front-input"
                      type="file"
                      accept={ACCEPTED_ACCEPT_ATTR}
                      onChange={(e) => handleFileSelect('front', e.target.files?.[0] ?? null)}
                    />
                    {frontImage && (
                      <p className="text-xs text-muted-foreground">{frontImage.name}</p>
                    )}
                    {frontPreview && (
                      <img
                        src={frontPreview}
                        alt="Xem trước mặt trước"
                        data-testid="kyc-front-preview"
                        className="mt-2 max-h-48 rounded-md border object-contain"
                      />
                    )}
                  </div>
                  <div className="space-y-2">
                    <Label htmlFor="backImg">Ảnh mặt sau</Label>
                    <Input
                      id="backImg"
                      data-testid="kyc-back-input"
                      type="file"
                      accept={ACCEPTED_ACCEPT_ATTR}
                      onChange={(e) => handleFileSelect('back', e.target.files?.[0] ?? null)}
                    />
                    {backImage && (
                      <p className="text-xs text-muted-foreground">{backImage.name}</p>
                    )}
                    {backPreview && (
                      <img
                        src={backPreview}
                        alt="Xem trước mặt sau"
                        data-testid="kyc-back-preview"
                        className="mt-2 max-h-48 rounded-md border object-contain"
                      />
                    )}
                  </div>
                  <div className="space-y-2">
                    <Label htmlFor="selfieImg">Ảnh selfie cầm giấy tờ</Label>
                    <Input
                      id="selfieImg"
                      data-testid="kyc-selfie-input"
                      type="file"
                      accept={ACCEPTED_ACCEPT_ATTR}
                      onChange={(e) => handleFileSelect('selfie', e.target.files?.[0] ?? null)}
                    />
                    {selfieImage && (
                      <p className="text-xs text-muted-foreground">{selfieImage.name}</p>
                    )}
                    {selfiePreview && (
                      <img
                        src={selfiePreview}
                        alt="Xem trước selfie"
                        data-testid="kyc-selfie-preview"
                        className="mt-2 max-h-48 rounded-md border object-contain"
                      />
                    )}
                  </div>
                </>
              )}

              {/* Step 3: Confirm */}
              {currentStep === 3 && (
                <div className="space-y-3 rounded-lg border bg-muted/50 p-4">
                  <h3 className="font-semibold">Kiểm tra thông tin</h3>
                  <div className="grid gap-2 text-sm">
                    <div className="flex justify-between">
                      <span className="text-muted-foreground">Loại giấy tờ</span>
                      <span>{DOCUMENT_TYPES.find((d) => d.value === documentType)?.label}</span>
                    </div>
                    <div className="flex justify-between">
                      <span className="text-muted-foreground">Số giấy tờ</span>
                      <span>{documentNumber}</span>
                    </div>
                    <div className="flex justify-between">
                      <span className="text-muted-foreground">Ảnh mặt trước</span>
                      <span>{frontImage ? frontImage.name : 'Chưa tải'}</span>
                    </div>
                    <div className="flex justify-between">
                      <span className="text-muted-foreground">Ảnh mặt sau</span>
                      <span>{backImage ? backImage.name : 'Không có'}</span>
                    </div>
                    <div className="flex justify-between">
                      <span className="text-muted-foreground">Ảnh selfie</span>
                      <span>{selfieImage ? selfieImage.name : 'Không có'}</span>
                    </div>
                  </div>
                </div>
              )}

              {/* Upload progress */}
              {submitting && Object.keys(uploadProgress).length > 0 && (
                <div className="space-y-2">
                  <div className="flex items-center justify-between text-sm">
                    <span className="text-muted-foreground">Đang tải ảnh lên...</span>
                    <span className="font-medium">{totalProgress()}%</span>
                  </div>
                  <div className="h-2 w-full overflow-hidden rounded-full bg-muted">
                    <div
                      className="h-full rounded-full bg-primary transition-all duration-300"
                      style={{ width: `${totalProgress()}%` }}
                    />
                  </div>
                </div>
              )}

              {/* Navigation buttons */}
              <div className="flex justify-between pt-2">
                {currentStep > 1 ? (
                  <Button
                    variant="outline"
                    data-testid="kyc-back-button"
                    onClick={() => setCurrentStep((s) => s - 1)}
                    disabled={submitting}
                  >
                    Quay lại
                  </Button>
                ) : (
                  <div />
                )}
                {currentStep < 3 ? (
                  <Button
                    data-testid="kyc-next-button"
                    onClick={() => {
                      if (currentStep === 1 && !documentNumber.trim()) {
                        setError('Vui lòng nhập số giấy tờ');
                        return;
                      }
                      if (currentStep === 2 && !frontImage) {
                        setError('Vui lòng tải ảnh mặt trước');
                        return;
                      }
                      setError(null);
                      setCurrentStep((s) => s + 1);
                    }}
                  >
                    Tiếp tục
                  </Button>
                ) : (
                  <Button
                    data-testid="kyc-submit-button"
                    onClick={handleSubmit}
                    disabled={submitting}
                  >
                    {submitting ? 'Đang gửi...' : 'Gửi hồ sơ xác minh'}
                  </Button>
                )}
              </div>
            </CardContent>
          </Card>
        </>
      )}

      {/* Already verified */}
      {kycStatus === 'VERIFIED' && (
        <Card>
          <CardContent className="flex flex-col items-center justify-center py-12">
            <div className="mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-green-100 text-green-700">
              <Check className="h-8 w-8" aria-hidden="true" />
            </div>
            <h2 className="text-xl font-semibold">Danh tính đã được xác minh</h2>
            <p className="mt-2 text-center text-sm text-muted-foreground">
              Tài khoản của bạn đã được xác minh đầy đủ. Bạn có thể sử dụng tất cả tính năng của
              GoodGo.
            </p>
          </CardContent>
        </Card>
      )}

      {/* Pending status */}
      {kycStatus === 'PENDING' && !success && (
        <Card>
          <CardContent className="flex flex-col items-center justify-center py-12">
            <div className="mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-yellow-100 text-3xl">
              ⏳
            </div>
            <h2 className="text-xl font-semibold">Đang xem xét hồ sơ</h2>
            <p className="mt-2 text-center text-sm text-muted-foreground">
              Đội ngũ quản trị đang xem xét hồ sơ của bạn. Thời gian dự kiến: 1-3 ngày làm việc.
            </p>
          </CardContent>
        </Card>
      )}
    </div>
  );
}
