import {
  pgTable,
  uuid,
  varchar,
  text,
  jsonb,
  timestamp,
  boolean,
  integer,
  bigint,
  index,
  uniqueIndex,
} from 'drizzle-orm/pg-core';
import { relations } from 'drizzle-orm';

// ═══════════════════════════════════════════════════════════
// NOTE: The actual PostgreSQL database uses custom enum types
// (pipeline_template, pipeline_stage, pipeline_status, etc.)
// but Drizzle ORM columns are defined as varchar to allow
// flexible string comparisons in service code. PostgreSQL
// will still enforce enum constraints at the database level.
// ═══════════════════════════════════════════════════════════

// ═══════════════════════════════════════════════════════════
// PIPELINES — Top-level entity, one per MCP server build
// ═══════════════════════════════════════════════════════════

export const pipelines = pgTable(
  'pipelines',
  {
    id: uuid('id').primaryKey().defaultRandom(),
    name: varchar('name', { length: 200 }).notNull(),
    slug: varchar('slug', { length: 200 }).unique().notNull(),
    template: varchar('template', { length: 100 }).notNull().default('mcp-server-standard'),
    platform: varchar('platform', { length: 100 }).notNull(),

    // State machine
    currentStage: varchar('current_stage', { length: 50 }).notNull().default('intake'),
    status: varchar('status', { length: 30 }).notNull().default('active'),
    priority: varchar('priority', { length: 20 }).notNull().default('medium'),

    // Ownership
    createdBy: uuid('created_by'),
    assigneeId: uuid('assignee_id'),

    // Configuration (JSONB for flexibility)
    config: jsonb('config').notNull().default({}),
    metadata: jsonb('metadata').notNull().default({}),

    // SLA tracking
    slaDeadline: timestamp('sla_deadline', { withTimezone: true }),
    startedAt: timestamp('started_at', { withTimezone: true }).notNull().defaultNow(),
    completedAt: timestamp('completed_at', { withTimezone: true }),

    // Timestamps
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  },
  (table) => [
    index('idx_pipelines_status').on(table.status),
    index('idx_pipelines_stage').on(table.currentStage),
    index('idx_pipelines_priority').on(table.priority),
  ]
);

// ═══════════════════════════════════════════════════════════
// PIPELINE_STAGES — Stage definitions & transitions per pipeline
// ═══════════════════════════════════════════════════════════

export const pipelineStages = pgTable(
  'pipeline_stages',
  {
    id: uuid('id').primaryKey().defaultRandom(),
    pipelineId: uuid('pipeline_id')
      .notNull()
      .references(() => pipelines.id, { onDelete: 'cascade' }),
    stageName: varchar('stage_name', { length: 50 }).notNull(),
    stageOrder: integer('stage_order').notNull(),

    // State
    status: varchar('status', { length: 30 }).notNull().default('pending'),

    // Gate configuration
    requiresApproval: boolean('requires_approval').notNull().default(false),
    approvalType: varchar('approval_type', { length: 20 }).notNull().default('manual'),
    autoAdvance: boolean('auto_advance').notNull().default(false),

    // Validation rules
    validationRules: jsonb('validation_rules').notNull().default([]),

    // Timing
    enteredAt: timestamp('entered_at', { withTimezone: true }),
    completedAt: timestamp('completed_at', { withTimezone: true }),
    durationSeconds: integer('duration_seconds'),

    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  },
  (table) => [
    uniqueIndex('idx_pipeline_stage_unique').on(table.pipelineId, table.stageName),
    index('idx_pipeline_stages_pipeline').on(table.pipelineId),
    index('idx_pipeline_stages_status').on(table.status),
  ]
);

// ═══════════════════════════════════════════════════════════
// TASKS — Work items requiring human decisions (the queue)
// ═══════════════════════════════════════════════════════════

export const tasks = pgTable(
  'tasks',
  {
    id: uuid('id').primaryKey().defaultRandom(),
    pipelineId: uuid('pipeline_id').references(() => pipelines.id),
    stageName: varchar('stage_name', { length: 50 }),

    // Task details
    type: varchar('type', { length: 50 }).notNull(),
    title: varchar('title', { length: 500 }).notNull(),
    description: text('description'),
    context: jsonb('context').notNull().default({}),

    // Queue management
    status: varchar('status', { length: 30 }).notNull().default('pending'),
    priority: varchar('priority', { length: 20 }).notNull().default('medium'),

    // Assignment
    assigneeId: uuid('assignee_id'),
    claimedAt: timestamp('claimed_at', { withTimezone: true }),
    claimedBy: uuid('claimed_by'),

    // Decision tracking
    decision: varchar('decision', { length: 30 }),
    decisionNotes: text('decision_notes'),
    decisionData: jsonb('decision_data').notNull().default({}),
    decidedAt: timestamp('decided_at', { withTimezone: true }),
    decidedBy: uuid('decided_by'),

    // SLA
    slaDeadline: timestamp('sla_deadline', { withTimezone: true }),
    slaWarningsSent: integer('sla_warnings_sent').notNull().default(0),
    slaBreached: boolean('sla_breached').notNull().default(false),
    escalationLevel: integer('escalation_level').notNull().default(0),

    // Blocking info
    blocksStageAdvance: boolean('blocks_stage_advance').notNull().default(false),
    blocksPipelineId: uuid('blocks_pipeline_id').references(() => pipelines.id),

    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  },
  (table) => [
    index('idx_tasks_status').on(table.status),
    index('idx_tasks_priority').on(table.priority),
    index('idx_tasks_sla').on(table.slaBreached, table.slaDeadline),
    index('idx_tasks_pipeline').on(table.pipelineId),
  ]
);

// ═══════════════════════════════════════════════════════════
// APPROVALS — Formal gate approvals (linked to tasks)
// ═══════════════════════════════════════════════════════════

export const approvals = pgTable(
  'approvals',
  {
    id: uuid('id').primaryKey().defaultRandom(),
    taskId: uuid('task_id').notNull().references(() => tasks.id),
    pipelineId: uuid('pipeline_id').notNull().references(() => pipelines.id),
    stageName: varchar('stage_name', { length: 50 }).notNull(),

    // Approval details
    type: varchar('type', { length: 30 }).notNull(),
    status: varchar('status', { length: 30 }).notNull().default('pending'),

    // Decision
    approvedBy: uuid('approved_by'),
    approvedAt: timestamp('approved_at', { withTimezone: true }),
    rejectionReason: text('rejection_reason'),
    conditions: jsonb('conditions').notNull().default([]),

    // Multi-party
    requiredApprovers: integer('required_approvers').notNull().default(1),
    currentApprovers: integer('current_approvers').notNull().default(0),

    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  },
  (table) => [
    index('idx_approvals_status').on(table.status),
    index('idx_approvals_pipeline').on(table.pipelineId),
  ]
);

// ═══════════════════════════════════════════════════════════
// AGENTS — AI workers and build/deploy agents
// ═══════════════════════════════════════════════════════════

export const agents = pgTable(
  'agents',
  {
    id: uuid('id').primaryKey().defaultRandom(),
    name: varchar('name', { length: 200 }).notNull(),
    type: varchar('type', { length: 50 }).notNull(),

    // Status
    status: varchar('status', { length: 30 }).notNull().default('idle'),
    currentTaskId: uuid('current_task_id').references(() => tasks.id),
    currentPipelineId: uuid('current_pipeline_id').references(() => pipelines.id),

    // Health (JSONB blob in DB)
    health: jsonb('health').notNull().default({}),

    // Health (individual columns)
    lastHeartbeat: timestamp('last_heartbeat', { withTimezone: true }),
    uptimeSeconds: integer('uptime_seconds').default(0),
    errorCount24h: integer('error_count_24h').default(0),

    // Configuration
    capabilities: jsonb('capabilities').notNull().default([]),
    config: jsonb('config').notNull().default({}),

    // Metrics
    tasksCompletedTotal: integer('tasks_completed_total').notNull().default(0),
    avgTaskDurationSeconds: integer('avg_task_duration_seconds'),

    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  },
  (table) => [
    index('idx_agents_status').on(table.status),
    index('idx_agents_type').on(table.type),
  ]
);

// ═══════════════════════════════════════════════════════════
// ASSETS — Generated files, code, configs, build artifacts
// ═══════════════════════════════════════════════════════════

export const assets = pgTable(
  'assets',
  {
    id: uuid('id').primaryKey().defaultRandom(),
    pipelineId: uuid('pipeline_id').references(() => pipelines.id),
    stageName: varchar('stage_name', { length: 50 }),

    // Asset info
    type: varchar('type', { length: 30 }).notNull(),
    name: varchar('name', { length: 500 }).notNull(),
    path: text('path'),

    // Storage
    storageKey: text('storage_key').notNull(),
    storageBucket: text('storage_bucket'),
    sizeBytes: bigint('size_bytes', { mode: 'number' }).default(0),
    contentType: varchar('content_type', { length: 100 }).default('application/octet-stream'),
    checksumSha256: varchar('checksum_sha256', { length: 64 }),

    // Versioning
    version: integer('version').notNull().default(1),
    previousVersionId: uuid('previous_version_id'),

    // Provenance
    generatedBy: uuid('generated_by'),
    generatorType: varchar('generator_type', { length: 30 }).notNull().default('agent'),

    metadata: jsonb('metadata').notNull().default({}),

    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  },
  (table) => [
    index('idx_assets_pipeline').on(table.pipelineId),
    index('idx_assets_type').on(table.type),
    index('idx_assets_stage').on(table.pipelineId, table.stageName),
  ]
);

// ═══════════════════════════════════════════════════════════
// NOTIFICATIONS — Multi-channel notification queue
// ═══════════════════════════════════════════════════════════

export const notifications = pgTable(
  'notifications',
  {
    id: uuid('id').primaryKey().defaultRandom(),
    userId: varchar('user_id', { length: 255 }).notNull(),

    // Content
    type: varchar('type', { length: 50 }).notNull(),
    title: varchar('title', { length: 500 }).notNull(),
    body: text('body'),
    data: jsonb('data').notNull().default({}),

    // Delivery
    channels: jsonb('channels').notNull().default([]),
    deliveredVia: jsonb('delivered_via').notNull().default([]),

    // Status
    read: boolean('read').notNull().default(false),
    readAt: timestamp('read_at', { withTimezone: true }),
    dismissed: boolean('dismissed').notNull().default(false),

    // Linking
    entityType: varchar('entity_type', { length: 100 }),
    entityId: uuid('entity_id'),
    actionUrl: text('action_url'),

    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  },
  (table) => [
    index('idx_notifications_user').on(table.userId, table.read),
    index('idx_notifications_entity').on(table.entityType, table.entityId),
  ]
);

// ═══════════════════════════════════════════════════════════
// AUDIT_LOG — Immutable event log
// ═══════════════════════════════════════════════════════════

export const auditLog = pgTable(
  'audit_log',
  {
    id: uuid('id').primaryKey().defaultRandom(),

    // Who
    actorType: varchar('actor_type', { length: 30 }).notNull(),
    actorId: varchar('actor_id', { length: 255 }),
    actorName: varchar('actor_name', { length: 200 }),

    // What
    action: varchar('action', { length: 200 }).notNull(),

    // On what
    entityType: varchar('entity_type', { length: 100 }).notNull(),
    entityId: varchar('entity_id', { length: 255 }),

    // Details
    changes: jsonb('changes').notNull().default({}),
    metadata: jsonb('metadata').notNull().default({}),

    // Immutable timestamp
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  },
  (table) => [
    index('idx_audit_entity').on(table.entityType, table.entityId),
    index('idx_audit_action').on(table.action),
    index('idx_audit_actor').on(table.actorType, table.actorId),
    index('idx_audit_time').on(table.createdAt),
  ]
);

// ═══════════════════════════════════════════════════════════
// WEBHOOKS — Registered webhook endpoints
// ═══════════════════════════════════════════════════════════

export const webhooks = pgTable(
  'webhooks',
  {
    id: uuid('id').primaryKey().defaultRandom(),
    url: text('url').notNull(),
    events: jsonb('events').notNull().default([]),
    secret: varchar('secret', { length: 256 }),
    active: boolean('active').notNull().default(true),
    createdBy: uuid('created_by'),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  },
  (table) => [
    index('idx_webhooks_active').on(table.active),
  ]
);

// ═══════════════════════════════════════════════════════════
// RELATIONS — Drizzle ORM relations for query builder
// ═══════════════════════════════════════════════════════════

export const pipelinesRelations = relations(pipelines, ({ many }) => ({
  stages: many(pipelineStages),
  tasks: many(tasks),
  approvals: many(approvals),
  assets: many(assets),
}));

export const pipelineStagesRelations = relations(pipelineStages, ({ one }) => ({
  pipeline: one(pipelines, {
    fields: [pipelineStages.pipelineId],
    references: [pipelines.id],
  }),
}));

export const tasksRelations = relations(tasks, ({ one, many }) => ({
  pipeline: one(pipelines, {
    fields: [tasks.pipelineId],
    references: [pipelines.id],
  }),
  approvals: many(approvals),
}));

export const approvalsRelations = relations(approvals, ({ one }) => ({
  task: one(tasks, {
    fields: [approvals.taskId],
    references: [tasks.id],
  }),
  pipeline: one(pipelines, {
    fields: [approvals.pipelineId],
    references: [pipelines.id],
  }),
}));

export const agentsRelations = relations(agents, ({ one }) => ({
  currentTask: one(tasks, {
    fields: [agents.currentTaskId],
    references: [tasks.id],
  }),
  currentPipeline: one(pipelines, {
    fields: [agents.currentPipelineId],
    references: [pipelines.id],
  }),
}));

export const assetsRelations = relations(assets, ({ one }) => ({
  pipeline: one(pipelines, {
    fields: [assets.pipelineId],
    references: [pipelines.id],
  }),
}));
