import { describe, it, expect, beforeEach } from 'vitest';
import { readFileSync } from 'fs';
import { resolve } from 'path';
import { useInputBarStore } from '../../src/store/inputBar';

function createMockFile(name: string, type: string, sizeInBytes?: number): File {
  const content = sizeInBytes ? new Uint8Array(sizeInBytes) : new Uint8Array([0]);
  return new File([content], name, { type });
}

describe('Bug Fix Verification — Previous Bugs', () => {
  describe('BUG-001: GenerationCard model display (was hardcoded)', () => {
    it('should use task.model dynamically in GenerationCard source', () => {
      const src = readFileSync(
        resolve(__dirname, '../../src/components/GenerationCard.tsx'),
        'utf-8'
      );
      // Should NOT contain a bare hardcoded "Seedance 2.0" in the meta section
      // Instead should reference task.model
      expect(src).toContain('task.model');
      // The ternary pattern confirms dynamic rendering
      expect(src).toMatch(/task\.model\s*===\s*'seedance_2\.0'/);
    });
  });

  describe('BUG-002: File size validation', () => {
    it('UniversalUpload should enforce image <20MB and video <100MB limits', () => {
      const src = readFileSync(
        resolve(__dirname, '../../src/components/UniversalUpload.tsx'),
        'utf-8'
      );
      expect(src).toContain('20 * 1024 * 1024');
      expect(src).toContain('100 * 1024 * 1024');
      expect(src).toContain('图片文件不能超过20MB');
      expect(src).toContain('视频文件不能超过100MB');
    });

    it('InputBar drag-drop should enforce file size limits', () => {
      const src = readFileSync(
        resolve(__dirname, '../../src/components/InputBar.tsx'),
        'utf-8'
      );
      expect(src).toContain('20 * 1024 * 1024');
      expect(src).toContain('100 * 1024 * 1024');
    });

    it('KeyframeUpload should enforce image <20MB limit', () => {
      const src = readFileSync(
        resolve(__dirname, '../../src/components/KeyframeUpload.tsx'),
        'utf-8'
      );
      expect(src).toContain('20 * 1024 * 1024');
      expect(src).toContain('图片文件不能超过20MB');
    });
  });

  describe('Original BUG-001: canSubmit selector (was stale reference)', () => {
    it('Toolbar should call canSubmit() as invocation, not reference', () => {
      const src = readFileSync(
        resolve(__dirname, '../../src/components/Toolbar.tsx'),
        'utf-8'
      );
      // Must be s.canSubmit() — the function call, not s.canSubmit (reference)
      expect(src).toMatch(/s\.canSubmit\(\)/);
    });
  });

  describe('Original BUG-002: drag-drop audio filter', () => {
    it('InputBar drag-drop should only accept image/* and video/*', () => {
      const src = readFileSync(
        resolve(__dirname, '../../src/components/InputBar.tsx'),
        'utf-8'
      );
      // Filter should only allow image and video, not audio
      expect(src).toContain("f.type.startsWith('image/')");
      expect(src).toContain("f.type.startsWith('video/')");
    });
  });
});

describe('File Upload Validation — Store Level', () => {
  beforeEach(() => {
    useInputBarStore.getState().reset();
  });

  it('should accept image files in universal mode', () => {
    const file = createMockFile('photo.jpg', 'image/jpeg');
    useInputBarStore.getState().addReferences([file]);
    expect(useInputBarStore.getState().references).toHaveLength(1);
    expect(useInputBarStore.getState().references[0].type).toBe('image');
  });

  it('should accept video files in universal mode', () => {
    const file = createMockFile('clip.mp4', 'video/mp4');
    useInputBarStore.getState().addReferences([file]);
    expect(useInputBarStore.getState().references).toHaveLength(1);
    expect(useInputBarStore.getState().references[0].type).toBe('video');
  });

  it('should accept only image files for first/last frames', () => {
    useInputBarStore.getState().switchMode('keyframe');
    const file = createMockFile('frame.jpg', 'image/jpeg');
    useInputBarStore.getState().setFirstFrame(file);
    expect(useInputBarStore.getState().firstFrame).not.toBeNull();
    expect(useInputBarStore.getState().firstFrame!.type).toBe('image');
  });

  it('keyframe file input should only accept image/*', () => {
    const src = readFileSync(
      resolve(__dirname, '../../src/components/KeyframeUpload.tsx'),
      'utf-8'
    );
    // Both inputs should have accept="image/*"
    const matches = src.match(/accept="image\/\*"/g);
    expect(matches).not.toBeNull();
    expect(matches!.length).toBe(2);
  });
});

describe('PRD Compliance — Code Structure Checks', () => {
  it('should have file upload accept limited to image/video in UniversalUpload', () => {
    const src = readFileSync(
      resolve(__dirname, '../../src/components/UniversalUpload.tsx'),
      'utf-8'
    );
    expect(src).toContain('accept="image/*,video/*"');
  });

  it('should have URL.revokeObjectURL calls for memory cleanup', () => {
    const storeSrc = readFileSync(
      resolve(__dirname, '../../src/store/inputBar.ts'),
      'utf-8'
    );
    const revokeCount = (storeSrc.match(/URL\.revokeObjectURL/g) || []).length;
    // Should have revokeObjectURL in: removeReference, clearReferences, setFirstFrame, setLastFrame, switchMode(x2), reset
    expect(revokeCount).toBeGreaterThanOrEqual(5);
  });

  it('should preserve prompt text across mode switches', () => {
    useInputBarStore.getState().setPrompt('my test prompt');
    useInputBarStore.getState().switchMode('keyframe');
    expect(useInputBarStore.getState().prompt).toBe('my test prompt');
    useInputBarStore.getState().switchMode('universal');
    expect(useInputBarStore.getState().prompt).toBe('my test prompt');
  });
});

describe('Dead Code Audit — Audio Dead Code Cleaned Up', () => {
  it('types/index.ts UploadedFile.type no longer includes audio', () => {
    const src = readFileSync(
      resolve(__dirname, '../../src/types/index.ts'),
      'utf-8'
    );
    // Audio type was cleaned up in a previous dev session
    const hasAudioType = src.includes("'audio'");
    expect(hasAudioType).toBe(false); // Verified: audio dead code has been removed
  });

  it('inputBar.ts addReferences no longer classifies audio files', () => {
    const src = readFileSync(
      resolve(__dirname, '../../src/store/inputBar.ts'),
      'utf-8'
    );
    const hasAudioClassification = src.includes("'audio'");
    expect(hasAudioClassification).toBe(false); // Verified: audio dead code has been removed
  });
});
