import { useState } from 'react';
import { defineStory, useBoolean, useNumber } from '@djangocfg/playground';
import { Card, CardContent, CardHeader, CardTitle } from '@djangocfg/ui-core/components';
import { ImageIcon, ClipboardPaste } from 'lucide-react';
import { Uploader } from './components/Uploader';
import { logger } from './utils';
import { UploadProvider } from './context';
import { UploadDropzone } from './components/UploadDropzone';
import { UploadPreviewList } from './components/UploadPreviewList';
import { UploadAddButton } from './components/UploadAddButton';
import { useUploadEvents } from './hooks/useUploadEvents';
import { useClipboardPaste } from './hooks/useClipboardPaste';
import { useUploadProvider } from './hooks/useUploadProvider';
import type { UploadedAsset, AssetType } from './types';

export default defineStory({
  title: 'Tools/Uploader',
  component: Uploader,
  description: 'Drag-drop file uploader with progress tracking and preview.',
});

// Mock upload endpoint that simulates server response
const MOCK_DESTINATION = 'https://httpbin.org/post';

export const Interactive = () => {
  const [compact] = useBoolean('compact', {
    defaultValue: false,
    label: 'Compact Mode',
  });

  const [showPreview] = useBoolean('showPreview', {
    defaultValue: true,
    label: 'Show Preview',
  });

  const [multiple] = useBoolean('multiple', {
    defaultValue: true,
    label: 'Multiple Files',
  });

  const [maxSizeMB] = useNumber('maxSizeMB', {
    defaultValue: 10,
    min: 1,
    max: 100,
    label: 'Max Size (MB)',
  });

  const [concurrent] = useNumber('concurrent', {
    defaultValue: 3,
    min: 1,
    max: 10,
    label: 'Concurrent Uploads',
  });

  const [uploadedFiles, setUploadedFiles] = useState<string[]>([]);

  return (
    <div className="max-w-2xl space-y-4">
      <Uploader
        destination={MOCK_DESTINATION}
        compact={compact}
        showPreview={showPreview}
        multiple={multiple}
        maxSizeMB={maxSizeMB}
        concurrent={concurrent}
        accept={['image', 'document']}
        onUploadComplete={(asset) => {
          setUploadedFiles((prev) => [...prev, asset.name]);
        }}
      />

      {uploadedFiles.length > 0 && (
        <Card>
          <CardHeader>
            <CardTitle className="text-sm">Uploaded Files</CardTitle>
          </CardHeader>
          <CardContent>
            <ul className="text-sm space-y-1">
              {uploadedFiles.map((name, i) => (
                <li key={i} className="text-muted-foreground">
                  {name}
                </li>
              ))}
            </ul>
          </CardContent>
        </Card>
      )}
    </div>
  );
};

export const Default = () => (
  <div className="max-w-2xl">
    <Uploader
      destination={MOCK_DESTINATION}
      accept={['image', 'video', 'document']}
    />
  </div>
);

export const ImagesOnly = () => (
  <div className="max-w-2xl">
    <Uploader
      destination={MOCK_DESTINATION}
      accept={['image']}
      maxSizeMB={5}
    />
  </div>
);

export const Compact = () => (
  <div className="max-w-md">
    <Uploader
      destination={MOCK_DESTINATION}
      compact
      accept={['image', 'document']}
    />
  </div>
);

export const NoPreview = () => (
  <div className="max-w-2xl">
    <Uploader
      destination={MOCK_DESTINATION}
      showPreview={false}
      accept={['image', 'document']}
    />
  </div>
);

export const SingleFile = () => (
  <div className="max-w-2xl">
    <Uploader
      destination={MOCK_DESTINATION}
      multiple={false}
      accept={['image']}
    />
  </div>
);

// Custom composition example
function CustomUploaderContent() {
  const [assets, setAssets] = useState<UploadedAsset[]>([]);

  useUploadEvents({
    onFileComplete: (asset) => {
      setAssets((prev) => [...prev, asset]);
    },
    onError: (error, fileName) => {
      logger.error(`Error uploading ${fileName}: ${error}`);
    },
  });

  return (
    <div className="grid grid-cols-2 gap-4">
      <div>
        <h3 className="text-sm font-medium mb-2">Drop Zone</h3>
        <UploadDropzone accept={['image']} />
      </div>
      <div>
        <h3 className="text-sm font-medium mb-2">Upload Queue</h3>
        <UploadPreviewList />
      </div>
    </div>
  );
}

export const CustomComposition = () => (
  <div className="max-w-3xl">
    <UploadProvider destination={{ url: MOCK_DESTINATION }}>
      <CustomUploaderContent />
    </UploadProvider>
  </div>
);

// With add button
function WithAddButtonContent() {
  return (
    <div className="space-y-4">
      <div className="flex items-center gap-2">
        <UploadAddButton accept={['image', 'document']} />
        <span className="text-sm text-muted-foreground">
          Click to add files
        </span>
      </div>
      <UploadPreviewList />
    </div>
  );
}

export const WithAddButton = () => (
  <div className="max-w-2xl">
    <UploadProvider destination={{ url: MOCK_DESTINATION }}>
      <WithAddButtonContent />
    </UploadProvider>
  </div>
);

export const DocumentsOnly = () => (
  <div className="max-w-2xl">
    <Uploader
      destination={MOCK_DESTINATION}
      accept={['document']}
      maxSizeMB={20}
    >
      <div className="text-center">
        <p className="text-muted-foreground">Drop PDF, DOC, or XLS files</p>
        <p className="text-xs text-muted-foreground/60 mt-1">
          Max 20MB per file
        </p>
      </div>
    </Uploader>
  </div>
);

export const CustomContent = () => (
  <div className="max-w-2xl">
    <Uploader
      destination={MOCK_DESTINATION}
      accept={['image']}
      compact
    >
      <div className="flex items-center gap-2">
        <span className="text-2xl">+</span>
        <span className="text-sm">Add images</span>
      </div>
    </Uploader>
  </div>
);

// Paste to upload
export const PasteToUpload = () => {
  const [pasteEnabled] = useBoolean('pasteEnabled', {
    defaultValue: true,
    label: 'Paste Enabled (Ctrl+V)',
  });

  return (
    <div className="max-w-2xl space-y-4">
      <Card>
        <CardContent className="pt-4">
          <p className="text-sm text-muted-foreground flex items-center gap-2">
            <ClipboardPaste className="h-4 w-4" />
            Copy an image anywhere, then press <kbd className="px-1 py-0.5 rounded bg-muted text-xs font-mono">Ctrl+V</kbd> to upload it.
            Supports: files, screenshots, copied images, base64 URLs, remote image URLs.
          </p>
        </CardContent>
      </Card>
      <Uploader
        destination={MOCK_DESTINATION}
        accept={['image']}
        pasteEnabled={pasteEnabled}
        onPasteNoMatch={() => logger.info('Paste: no uploadable content found')}
      />
    </div>
  );
};

// useClipboardPaste hook standalone
function ClipboardPasteHookContent() {
  const { upload } = useUploadProvider();
  const [lastPaste, setLastPaste] = useState<string | null>(null);

  useClipboardPaste({
    enabled: true,
    acceptTypes: ['image'],
    onFiles: (files) => {
      setLastPaste(`Pasted ${files.length} file(s): ${files.map((f) => f.name).join(', ')}`);
      upload(files);
    },
    onNoMatch: () => setLastPaste('Paste detected but no image found in clipboard'),
  });

  return (
    <div className="space-y-4">
      <Card>
        <CardContent className="pt-4 space-y-2">
          <p className="text-sm text-muted-foreground flex items-center gap-2">
            <ClipboardPaste className="h-4 w-4" />
            Using <code className="text-xs bg-muted px-1 rounded">useClipboardPaste</code> hook directly — paste anywhere on the page.
          </p>
          {lastPaste && (
            <p className="text-xs font-mono bg-muted rounded p-2">{lastPaste}</p>
          )}
        </CardContent>
      </Card>
      <UploadPreviewList />
    </div>
  );
}

export const ClipboardPasteHook = () => (
  <div className="max-w-2xl">
    <UploadProvider destination={{ url: MOCK_DESTINATION }}>
      <ClipboardPasteHookContent />
    </UploadProvider>
  </div>
);

// Page-level drop zone
function PageDropContent() {
  return (
    <div className="space-y-4">
      <Card>
        <CardHeader>
          <CardTitle className="text-sm">Page Drop Enabled</CardTitle>
        </CardHeader>
        <CardContent>
          <p className="text-sm text-muted-foreground mb-4">
            Drag files anywhere on the page to upload. An overlay will appear when dragging.
          </p>
          <UploadPreviewList />
        </CardContent>
      </Card>
    </div>
  );
}

export const PageDrop = () => (
  <div className="max-w-2xl">
    <UploadProvider
      destination={{ url: MOCK_DESTINATION }}
      pageDropEnabled
      pageDropProps={{
        accept: ['image', 'document'],
        maxSizeMB: 10,
      }}
    >
      <PageDropContent />
    </UploadProvider>
  </div>
);

// Page drop with custom overlay
function PageDropCustomOverlayContent() {
  return (
    <div className="space-y-4">
      <Card>
        <CardHeader>
          <CardTitle className="text-sm">Custom Page Drop Overlay</CardTitle>
        </CardHeader>
        <CardContent>
          <p className="text-sm text-muted-foreground mb-4">
            This example uses a custom overlay design.
          </p>
          <UploadPreviewList />
        </CardContent>
      </Card>
    </div>
  );
}

export const PageDropCustomOverlay = () => (
  <div className="max-w-2xl">
    <UploadProvider
      destination={{ url: MOCK_DESTINATION }}
      pageDropEnabled
      pageDropProps={{
        accept: ['image'],
      }}
      pageDropOverlay={
        <div className="text-center p-12 bg-primary/10 rounded-2xl border-4 border-dashed border-primary">
          <ImageIcon className="h-16 w-16 text-primary mx-auto mb-4" />
          <p className="text-xl font-bold text-primary">Drop your images here!</p>
        </div>
      }
    >
      <PageDropCustomOverlayContent />
    </UploadProvider>
  </div>
);

// Standalone — uploadFn instead of UploadProvider (custom API hooks, no rpldy)
export const StandaloneWithUploadFn = () => {
  const [files, setFiles] = useState<string[]>([]);

  return (
    <div className="max-w-2xl space-y-4">
      <Card>
        <CardContent className="pt-4">
          <p className="text-sm text-muted-foreground flex items-center gap-2">
            <ClipboardPaste className="h-4 w-4" />
            No <code className="text-xs bg-muted px-1 rounded">UploadProvider</code> needed.
            Pass <code className="text-xs bg-muted px-1 rounded">uploadFn</code> to handle files yourself.
            Drag, click, or paste (Ctrl+V).
          </p>
        </CardContent>
      </Card>
      <UploadDropzone
        accept={['image', 'document']}
        maxSizeMB={10}
        pasteEnabled
        uploadFn={(selected) => {
          setFiles((prev) => [...prev, ...selected.map((f) => f.name)]);
          logger.info('Custom uploadFn received: ' + selected.map((f) => f.name).join(', '));
        }}
        onPasteNoMatch={() => logger.info('Paste: no uploadable content found')}
      />
      {files.length > 0 && (
        <Card>
          <CardHeader>
            <CardTitle className="text-sm">Received by uploadFn</CardTitle>
          </CardHeader>
          <CardContent>
            <ul className="text-sm space-y-1">
              {files.map((name, i) => (
                <li key={i} className="text-muted-foreground">{name}</li>
              ))}
            </ul>
          </CardContent>
        </Card>
      )}
    </div>
  );
};
