import type { Plugin } from 'vite';
import * as fs from 'fs';
import * as path from 'path';
import { v4 as uuidv4 } from 'uuid';
import formidable from 'formidable';

interface MediaAsset {
  id: string;
  name: string;
  path: string;
  type: 'image' | 'audio' | 'animation' | 'folder';
  size?: number;
  mimeType?: string;
  createdAt: string;
  parentPath?: string;
}

/**
 * Media Management API Plugin
 * Provides API endpoints for managing media assets (images, audio, animations, folders)
 */
export function mediaManagementApiPlugin(): Plugin {
  let mediaDir: string;

  return {
    name: 'media-management-api',
    
    configureServer(server) {
      // Set media directory path
      mediaDir = path.join(process.cwd(), 'assets', 'media');
      
      // Ensure media directory exists
      if (!fs.existsSync(mediaDir)) {
        fs.mkdirSync(mediaDir, { recursive: true });
      }

      // Helper functions
      const sendJSON = (res: any, statusCode: number, data: any) => {
        res.statusCode = statusCode;
        res.setHeader('Content-Type', 'application/json; charset=utf-8');
        res.end(JSON.stringify(data));
      };

      const sendError = (res: any, statusCode: number, message: string) => {
        sendJSON(res, statusCode, { error: message, timestamp: new Date().toISOString() });
      };

      const getAssetType = (filePath: string, isDirectory: boolean): MediaAsset['type'] => {
        if (isDirectory) return 'folder';
        
        const ext = path.extname(filePath).toLowerCase();
        const mimeTypes: Record<string, MediaAsset['type']> = {
          '.jpg': 'image',
          '.jpeg': 'image',
          '.png': 'image',
          '.gif': 'image',
          '.webp': 'image',
          '.svg': 'image',
          '.mp3': 'audio',
          '.wav': 'audio',
          '.ogg': 'audio',
          '.m4a': 'audio',
          '.json': 'animation',
        };
        
        return mimeTypes[ext] || 'image';
      };

      const scanDirectory = (dirPath: string, relativePath: string = ''): MediaAsset[] => {
        const assets: MediaAsset[] = [];
        
        try {
          const items = fs.readdirSync(dirPath);
          
          for (const item of items) {
            // Skip hidden files
            if (item.startsWith('.')) continue;
            
            const fullPath = path.join(dirPath, item);
            const itemRelativePath = relativePath ? `${relativePath}/${item}` : item;
            const stats = fs.statSync(fullPath);
            
            const asset: MediaAsset = {
              id: uuidv4(),
              name: item,
              path: itemRelativePath,
              type: getAssetType(fullPath, stats.isDirectory()),
              createdAt: stats.birthtime.toISOString(),
              parentPath: relativePath || undefined,
            };

            if (!stats.isDirectory()) {
              asset.size = stats.size;
              asset.mimeType = getMimeType(fullPath);
            }

            assets.push(asset);
          }
        } catch (error: any) {
          console.error('Error scanning directory:', error);
        }
        
        return assets;
      };

      const getMimeType = (filePath: string): string => {
        const ext = path.extname(filePath).toLowerCase();
        const mimeTypes: Record<string, string> = {
          '.jpg': 'image/jpeg',
          '.jpeg': 'image/jpeg',
          '.png': 'image/png',
          '.gif': 'image/gif',
          '.webp': 'image/webp',
          '.svg': 'image/svg+xml',
          '.mp3': 'audio/mpeg',
          '.wav': 'audio/wav',
          '.ogg': 'audio/ogg',
          '.m4a': 'audio/mp4',
          '.json': 'application/json',
        };
        return mimeTypes[ext] || 'application/octet-stream';
      };

      // Middleware to handle API routes
      server.middlewares.use(async (req, res, next) => {
        const url = req.url || '';
        
        // GET /api/media - List media assets
        if (url.startsWith('/api/media') && req.method === 'GET') {
          try {
            const urlObj = new URL(url, `http://${req.headers.host}`);
            const requestedPath = urlObj.searchParams.get('path') || '';
            
            const targetDir = requestedPath 
              ? path.join(mediaDir, requestedPath)
              : mediaDir;
            
            if (!fs.existsSync(targetDir)) {
              return sendError(res, 404, 'Directory not found');
            }
            
            const assets = scanDirectory(targetDir, requestedPath);
            sendJSON(res, 200, assets);
          } catch (error: any) {
            console.error('Error listing media:', error);
            sendError(res, 500, error.message || 'Failed to list media assets');
          }
          return;
        }

        // POST /api/media/upload - Upload file
        if (url === '/api/media/upload' && req.method === 'POST') {
          try {
            const form = formidable({
              uploadDir: mediaDir,
              keepExtensions: true,
              maxFileSize: 50 * 1024 * 1024, // 50MB
            });

            form.parse(req, (err, fields, files) => {
              if (err) {
                return sendError(res, 400, 'Upload failed: ' + err.message);
              }

              try {
                const file = Array.isArray(files.file) ? files.file[0] : files.file;
                if (!file) {
                  return sendError(res, 400, 'No file uploaded');
                }

                const targetPath = Array.isArray(fields.path) ? fields.path[0] : fields.path;
                const targetDir = targetPath ? path.join(mediaDir, targetPath) : mediaDir;
                
                if (!fs.existsSync(targetDir)) {
                  fs.mkdirSync(targetDir, { recursive: true });
                }

                const finalPath = path.join(targetDir, file.originalFilename || file.newFilename);
                fs.renameSync(file.filepath, finalPath);

                sendJSON(res, 200, { 
                  message: 'File uploaded successfully',
                  path: path.relative(mediaDir, finalPath)
                });
              } catch (error: any) {
                sendError(res, 500, 'Failed to save file: ' + error.message);
              }
            });
          } catch (error: any) {
            sendError(res, 500, error.message || 'Upload failed');
          }
          return;
        }

        // POST /api/media/folder - Create folder
        if (url === '/api/media/folder' && req.method === 'POST') {
          try {
            let body = '';
            req.on('data', chunk => body += chunk);
            req.on('end', () => {
              try {
                const { name, parentPath } = JSON.parse(body);
                
                if (!name || !name.trim()) {
                  return sendError(res, 400, 'Folder name is required');
                }

                const targetDir = parentPath 
                  ? path.join(mediaDir, parentPath, name)
                  : path.join(mediaDir, name);

                if (fs.existsSync(targetDir)) {
                  return sendError(res, 400, 'Folder already exists');
                }

                fs.mkdirSync(targetDir, { recursive: true });
                sendJSON(res, 200, { 
                  message: 'Folder created successfully',
                  path: path.relative(mediaDir, targetDir)
                });
              } catch (error: any) {
                sendError(res, 400, 'Invalid request: ' + error.message);
              }
            });
          } catch (error: any) {
            sendError(res, 500, error.message || 'Failed to create folder');
          }
          return;
        }

        // DELETE /api/media/:path - Delete file or folder
        if (url.startsWith('/api/media/') && req.method === 'DELETE') {
          try {
            const assetPath = decodeURIComponent(url.replace('/api/media/', ''));
            const fullPath = path.join(mediaDir, assetPath);

            if (!fs.existsSync(fullPath)) {
              return sendError(res, 404, 'Asset not found');
            }

            const stats = fs.statSync(fullPath);
            if (stats.isDirectory()) {
              fs.rmSync(fullPath, { recursive: true, force: true });
            } else {
              fs.unlinkSync(fullPath);
            }

            sendJSON(res, 200, { message: 'Asset deleted successfully' });
          } catch (error: any) {
            console.error('Error deleting asset:', error);
            sendError(res, 500, error.message || 'Failed to delete asset');
          }
          return;
        }

        // GET /api/media/file/:path - Serve file
        if (url.startsWith('/api/media/file/') && req.method === 'GET') {
          try {
            const assetPath = decodeURIComponent(url.replace('/api/media/file/', ''));
            const fullPath = path.join(mediaDir, assetPath);

            if (!fs.existsSync(fullPath) || fs.statSync(fullPath).isDirectory()) {
              return sendError(res, 404, 'File not found');
            }

            const mimeType = getMimeType(fullPath);
            res.setHeader('Content-Type', mimeType);
            fs.createReadStream(fullPath).pipe(res);
          } catch (error: any) {
            console.error('Error serving file:', error);
            sendError(res, 500, error.message || 'Failed to serve file');
          }
          return;
        }

        next();
      });
    }
  };
}
