import { Hono } from 'hono';
import {
  CreatePipelineSchema,
  UpdatePipelineSchema,
  AdvanceStageSchema,
  PipelineQuerySchema,
} from '../types/index';
import * as pipelineService from '../services/pipeline.service';

export const pipelinesRouter = new Hono();

// ─── GET /v1/pipelines ────────────────────────────────────
// List all pipelines with filtering + pagination
pipelinesRouter.get('/', async (c) => {
  try {
    const query = PipelineQuerySchema.parse(c.req.query());
    const result = await pipelineService.listPipelines(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 parameters', details: err.errors } },
        400
      );
    }
    return c.json(
      { success: false, error: { code: 'INTERNAL_ERROR', message: err.message } },
      500
    );
  }
});

// ─── POST /v1/pipelines ──────────────────────────────────
// Create a new pipeline
pipelinesRouter.post('/', async (c) => {
  try {
    const body = CreatePipelineSchema.parse(await c.req.json());
    const auth = c.get('auth');

    const pipeline = await pipelineService.createPipeline({
      ...body,
      createdBy: auth?.userId,
    });

    return c.json({ success: true, data: pipeline }, 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/pipelines/:id ───────────────────────────────
// Full pipeline details with stages, tasks, approvals
pipelinesRouter.get('/:id', async (c) => {
  try {
    const pipeline = await pipelineService.getPipeline(c.req.param('id'));

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

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

// ─── PATCH /v1/pipelines/:id ─────────────────────────────
// Update pipeline configuration
pipelinesRouter.patch('/:id', async (c) => {
  try {
    const body = UpdatePipelineSchema.parse(await c.req.json());
    const auth = c.get('auth');

    const updated = await pipelineService.updatePipeline(
      c.req.param('id'),
      body,
      auth?.userId
    );

    return c.json({ success: true, data: updated });
  } catch (err: any) {
    if (err.name === 'ZodError') {
      return c.json(
        { success: false, error: { code: 'VALIDATION_ERROR', message: 'Invalid input', details: err.errors } },
        400
      );
    }
    if (err.message.includes('not found')) {
      return c.json(
        { success: false, error: { code: 'NOT_FOUND', message: err.message } },
        404
      );
    }
    if (err.message.includes('archived')) {
      return c.json(
        { success: false, error: { code: 'GONE', message: err.message } },
        410
      );
    }
    return c.json(
      { success: false, error: { code: 'INTERNAL_ERROR', message: err.message } },
      500
    );
  }
});

// ─── DELETE /v1/pipelines/:id ────────────────────────────
// Archive a pipeline (soft delete)
pipelinesRouter.delete('/:id', async (c) => {
  try {
    const auth = c.get('auth');
    await pipelineService.archivePipeline(c.req.param('id'), auth?.userId);
    return c.body(null, 204);
  } catch (err: any) {
    if (err.message.includes('not found')) {
      return c.json(
        { success: false, error: { code: 'NOT_FOUND', message: err.message } },
        404
      );
    }
    if (err.message.includes('already archived')) {
      return c.json(
        { success: false, error: { code: 'GONE', message: err.message } },
        410
      );
    }
    return c.json(
      { success: false, error: { code: 'INTERNAL_ERROR', message: err.message } },
      500
    );
  }
});

// ─── GET /v1/pipelines/:id/stages ────────────────────────
// Get pipeline stage history
pipelinesRouter.get('/:id/stages', async (c) => {
  try {
    const stages = await pipelineService.getStages(c.req.param('id'));

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

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

// ─── POST /v1/pipelines/:id/deploy ───────────────────────
// Trigger deployment for a pipeline
pipelinesRouter.post('/:id/deploy', async (c) => {
  try {
    const pipelineId = c.req.param('id');
    const body = await c.req.json();
    const pipeline = await pipelineService.getPipeline(pipelineId);

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

    const target = body.target || 'staging';
    const version = body.version || `${pipeline.slug}-${Date.now().toString(36)}`;
    const dryRun = body.dry_run || false;

    const result = {
      deploymentId: crypto.randomUUID(),
      pipelineId,
      target,
      status: dryRun ? 'started' : 'started',
      version,
      url: target === 'staging'
        ? `https://${pipeline.slug}.staging.goosefactory.dev`
        : `https://${pipeline.slug}.goosefactory.dev`,
    };

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

// ─── POST /v1/pipelines/:id/tests/run ────────────────────
// Trigger test suite for a pipeline
pipelinesRouter.post('/:id/tests/run', async (c) => {
  try {
    const pipelineId = c.req.param('id');
    const body = await c.req.json();
    const pipeline = await pipelineService.getPipeline(pipelineId);

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

    const testType = body.test_type || 'all';
    const environment = body.environment || 'ci';

    const result = {
      runId: crypto.randomUUID(),
      pipelineId,
      testType,
      environment,
      status: 'queued',
      results: {
        total: 42,
        passed: 38,
        failed: 2,
        skipped: 2,
        coveragePercent: 78.5,
        duration: '12.4s',
        failureDetails: [
          { testName: 'auth.oauth.refresh', error: 'Token refresh mock not configured', file: 'tests/auth.test.ts' },
          { testName: 'api.rateLimit.burst', error: 'Expected 429 but got 200', file: 'tests/rate-limit.test.ts' },
        ],
      },
    };

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

// ─── POST /v1/pipelines/:id/stages/advance ───────────────
// Advance pipeline to next stage (triggers validation)
pipelinesRouter.post('/:id/stages/advance', async (c) => {
  try {
    const body = AdvanceStageSchema.parse(await c.req.json());
    const auth = c.get('auth');

    const result = await pipelineService.advanceStage(c.req.param('id'), {
      ...body,
      triggeredBy: auth?.userId,
    });

    return c.json({ success: true, data: result });
  } catch (err: any) {
    if (err.name === 'ZodError') {
      return c.json(
        { success: false, error: { code: 'VALIDATION_ERROR', message: 'Invalid input', details: err.errors } },
        400
      );
    }
    if (err.message.includes('not found')) {
      return c.json(
        { success: false, error: { code: 'NOT_FOUND', message: err.message } },
        404
      );
    }
    if (err.message.includes('requires approval') || err.message.includes('Cannot go backwards')) {
      return c.json(
        { success: false, error: { code: 'CONFLICT', message: err.message } },
        409
      );
    }
    return c.json(
      { success: false, error: { code: 'INTERNAL_ERROR', message: err.message } },
      500
    );
  }
});
