import { Hono } from 'hono';
import { AssetQuerySchema, CreateAssetSchema, AssetDiffQuerySchema } from '../types/index';
import * as assetService from '../services/asset.service';

export const assetsRouter = new Hono();

// ─── GET /v1/assets ─────────────────────────────────────
// List assets (general query, pipelineId as query param)
assetsRouter.get('/', async (c) => {
  try {
    const pipelineId = c.req.query('pipeline_id');
    if (!pipelineId) {
      return c.json(
        { success: false, error: { code: 'VALIDATION_ERROR', message: 'pipeline_id query parameter is required' } },
        400
      );
    }

    const query = AssetQuerySchema.parse(c.req.query());
    const result = await assetService.listAssets(pipelineId, query);

    return c.json({
      success: true,
      data: result.items,
      meta: result.meta,
    });
  } catch (err: any) {
    if (err.name === 'ZodError') {
      return c.json(
        { success: false, error: { code: 'VALIDATION_ERROR', message: 'Invalid query', details: err.errors } },
        400
      );
    }
    return c.json(
      { success: false, error: { code: 'INTERNAL_ERROR', message: err.message } },
      500
    );
  }
});

// ─── POST /v1/assets ────────────────────────────────────
// Upload an asset (accepts JSON or multipart)
assetsRouter.post('/', async (c) => {
  try {
    const contentType = c.req.header('Content-Type') || '';
    const auth = c.get('auth');
    let data: any;
    let fileBuffer: Buffer | undefined;

    if (contentType.includes('multipart/form-data')) {
      // Handle multipart upload
      const formData = await c.req.formData();
      const file = formData.get('file') as File | null;

      data = {
        pipelineId: formData.get('pipelineId') as string || formData.get('pipeline_id') as string,
        stage: formData.get('stage') as string || undefined,
        type: formData.get('type') as string,
        name: file?.name || formData.get('name') as string,
        path: formData.get('path') as string || undefined,
        contentType: file?.type || formData.get('content_type') as string || undefined,
        metadata: formData.get('metadata') ? JSON.parse(formData.get('metadata') as string) : undefined,
      };

      if (file) {
        const arrayBuffer = await file.arrayBuffer();
        fileBuffer = Buffer.from(arrayBuffer);
        data.contentType = data.contentType || file.type;
        data.name = data.name || file.name;
      }
    } else {
      // JSON body
      const body = await c.req.json();
      data = {
        pipelineId: body.pipeline_id || body.pipelineId,
        stage: body.stage,
        type: body.type,
        name: body.name,
        path: body.path,
        contentType: body.content_type || body.contentType,
        metadata: body.metadata,
      };
    }

    // Validate core fields
    const validated = CreateAssetSchema.parse(data);

    const asset = await assetService.createAsset({
      ...validated,
      fileBuffer,
      generatedBy: auth?.userId,
      generatorType: auth?.role === 'agent' ? 'agent' : 'user',
    });

    return c.json({ success: true, data: asset }, 201);
  } catch (err: any) {
    if (err.name === 'ZodError') {
      return c.json(
        { success: false, error: { code: 'VALIDATION_ERROR', message: 'Invalid input', details: err.errors } },
        400
      );
    }
    return c.json(
      { success: false, error: { code: 'INTERNAL_ERROR', message: err.message } },
      500
    );
  }
});

// ─── GET /v1/assets/:id ────────────────────────────────
// Asset metadata
assetsRouter.get('/:id', async (c) => {
  try {
    const asset = await assetService.getAsset(c.req.param('id'));

    if (!asset) {
      return c.json(
        { success: false, error: { code: 'NOT_FOUND', message: 'Asset not found' } },
        404
      );
    }

    return c.json({ success: true, data: asset });
  } catch (err: any) {
    return c.json(
      { success: false, error: { code: 'INTERNAL_ERROR', message: err.message } },
      500
    );
  }
});

// ─── GET /v1/assets/:id/download ────────────────────────
// Download asset binary
assetsRouter.get('/:id/download', async (c) => {
  try {
    const info = await assetService.getAssetDownloadInfo(c.req.param('id'));

    if (!info) {
      return c.json(
        { success: false, error: { code: 'NOT_FOUND', message: 'Asset not found' } },
        404
      );
    }

    // In production: stream from S3/R2
    // For now: return metadata with storage key for client-side download
    return c.json({
      success: true,
      data: {
        storageKey: info.storageKey,
        contentType: info.contentType,
        sizeBytes: info.sizeBytes,
        message: 'In production, this endpoint streams the file binary. Storage key provided for direct access.',
      },
    });
  } catch (err: any) {
    return c.json(
      { success: false, error: { code: 'INTERNAL_ERROR', message: err.message } },
      500
    );
  }
});

// ─── GET /v1/assets/:id/diff ────────────────────────────
// Diff between versions
assetsRouter.get('/:id/diff', async (c) => {
  try {
    const query = AssetDiffQuerySchema.parse(c.req.query());
    const diff = await assetService.getAssetDiff(
      c.req.param('id'),
      query.fromVersion,
      query.toVersion
    );

    if (!diff) {
      return c.json(
        { success: false, error: { code: 'NOT_FOUND', message: 'Asset or version not found' } },
        404
      );
    }

    return c.json({ success: true, data: diff });
  } catch (err: any) {
    if (err.name === 'ZodError') {
      return c.json(
        { success: false, error: { code: 'VALIDATION_ERROR', message: 'Invalid query', details: err.errors } },
        400
      );
    }
    return c.json(
      { success: false, error: { code: 'INTERNAL_ERROR', message: err.message } },
      500
    );
  }
});
