import { z } from 'zod'
import { UuidSchema } from '../platform/utils/validation'

/**
 * Project Management API Schemas
 *
 * Request/response validation for /api/external/projects surface.
 * Used by both the API (external-routes.ts) and the CLI (packages/cli).
 *
 * Table mapping:
 *   prj_projects   -> ProjectSchemas
 *   prj_milestones -> MilestoneSchemas
 *   prj_tasks      -> TaskSchemas
 *   prj_notes      -> NoteSchemas
 */

// ---------------------------------------------------------------------------
// Enum literals (must match DB CHECK constraints exactly)
// ---------------------------------------------------------------------------

export const ProjectKindSchema = z.enum(['client_engagement', 'internal', 'research', 'other'])
export const ProjectStatusSchema = z.enum(['active', 'on_track', 'at_risk', 'blocked', 'completed', 'paused'])
export const MilestoneStatusSchema = z.enum(['upcoming', 'in_progress', 'completed', 'overdue', 'blocked'])
export const TaskStatusSchema = z.enum([
  'planned',
  'in_progress',
  'blocked',
  'completed',
  'cancelled',
  'submitted',
  'approved',
  'rejected',
  'revision_requested'
])
export const TaskTypeSchema = z.enum([
  'documentation',
  'code',
  'report',
  'design',
  'refactor',
  'feature',
  'bug',
  'research',
  'other'
])
export const NoteTypeSchema = z.enum(['call_note', 'status_update', 'issue', 'blocker', 'agent_learning'])

// ---------------------------------------------------------------------------
// Checklist item shape (JSONB array stored on prj_tasks)
// ---------------------------------------------------------------------------

export const ChecklistItemSchema = z.object({
  id: z.string(),
  label: z.string(),
  completed: z.boolean()
})

export const ChecklistSchema = z.array(ChecklistItemSchema)

// ---------------------------------------------------------------------------
// resume_context shape (JSONB on prj_tasks, merged on PATCH .../resume-context)
// ---------------------------------------------------------------------------

export const ResumeContextSchema = z.record(z.string(), z.unknown())

// ---------------------------------------------------------------------------
// Projects
// ---------------------------------------------------------------------------

export const CreateProjectRequestSchema = z
  .object({
    name: z.string().trim().min(1).max(255),
    kind: ProjectKindSchema,
    status: ProjectStatusSchema.optional(),
    description: z.string().nullable().optional(),
    deal_id: UuidSchema.nullable().optional(),
    client_id: UuidSchema.nullable().optional(),
    client_company_id: UuidSchema.nullable().optional(),
    start_date: z.string().nullable().optional(),
    target_end_date: z.string().nullable().optional(),
    contract_value: z.number().nullable().optional(),
    metadata: z.record(z.string(), z.unknown()).nullable().optional()
  })
  .strict()

export const UpdateProjectRequestSchema = z
  .object({
    name: z.string().trim().min(1).max(255).optional(),
    kind: ProjectKindSchema.optional(),
    status: ProjectStatusSchema.optional(),
    description: z.string().nullable().optional(),
    deal_id: UuidSchema.nullable().optional(),
    client_id: UuidSchema.nullable().optional(),
    client_company_id: UuidSchema.nullable().optional(),
    start_date: z.string().nullable().optional(),
    target_end_date: z.string().nullable().optional(),
    actual_end_date: z.string().nullable().optional(),
    contract_value: z.number().nullable().optional(),
    metadata: z.record(z.string(), z.unknown()).nullable().optional()
  })
  .strict()
  .refine((data) => Object.keys(data).length > 0, { message: 'At least one field must be provided' })

export const GetProjectsQuerySchema = z
  .object({
    kind: ProjectKindSchema.optional(),
    status: ProjectStatusSchema.optional(),
    search: z.string().trim().min(1).max(255).optional(),
    client_id: UuidSchema.optional()
  })
  .strict()

export const ProjectIdParamsSchema = z.object({ id: UuidSchema })

export const ProjectSourceDealRefSchema = z.object({
  id: z.string(),
  clientId: z.string().nullable().optional(),
  contactEmail: z.string(),
  stageKey: z.string().nullable(),
  stateKey: z.string().nullable(),
  sourceListId: z.string().nullable(),
  updatedAt: z.string()
})

export const ProjectClientRefSchema = z.object({
  id: z.string(),
  name: z.string(),
  status: z.string()
})

// ---------------------------------------------------------------------------
// Milestones
// ---------------------------------------------------------------------------

export const CreateMilestoneRequestSchema = z
  .object({
    name: z.string().trim().min(1).max(255),
    status: MilestoneStatusSchema.optional(),
    description: z.string().nullable().optional(),
    due_date: z.string().nullable().optional(),
    sequence: z.number().int().min(0).optional(),
    metadata: z.record(z.string(), z.unknown()).nullable().optional()
  })
  .strict()

export const UpdateMilestoneRequestSchema = z
  .object({
    name: z.string().trim().min(1).max(255).optional(),
    status: MilestoneStatusSchema.optional(),
    description: z.string().nullable().optional(),
    due_date: z.string().nullable().optional(),
    completed_at: z.string().nullable().optional(),
    sequence: z.number().int().min(0).optional(),
    checklist: ChecklistSchema.optional(),
    metadata: z.record(z.string(), z.unknown()).nullable().optional()
  })
  .strict()
  .refine((data) => Object.keys(data).length > 0, { message: 'At least one field must be provided' })

export const ProjectIdPathParamsSchema = z.object({ projectId: UuidSchema })
export const MilestoneIdParamsSchema = z.object({ id: UuidSchema })

// ---------------------------------------------------------------------------
// Tasks
// ---------------------------------------------------------------------------

export const CreateTaskRequestSchema = z
  .object({
    project_id: UuidSchema,
    name: z.string().trim().min(1).max(255),
    type: TaskTypeSchema.optional(),
    status: TaskStatusSchema.optional(),
    description: z.string().nullable().optional(),
    milestone_id: UuidSchema.nullable().optional(),
    parent_task_id: UuidSchema.nullable().optional(),
    due_date: z.string().nullable().optional(),
    checklist: ChecklistSchema.optional(),
    resume_context: ResumeContextSchema.nullable().optional(),
    metadata: z.record(z.string(), z.unknown()).nullable().optional()
  })
  .strict()

export const UpdateTaskRequestSchema = z
  .object({
    name: z.string().trim().min(1).max(255).optional(),
    type: TaskTypeSchema.optional(),
    status: TaskStatusSchema.optional(),
    description: z.string().nullable().optional(),
    milestone_id: UuidSchema.nullable().optional(),
    parent_task_id: UuidSchema.nullable().optional(),
    due_date: z.string().nullable().optional(),
    completed_at: z.string().nullable().optional(),
    checklist: ChecklistSchema.optional(),
    resume_context: ResumeContextSchema.nullable().optional(),
    file_url: z.string().nullable().optional(),
    metadata: z.record(z.string(), z.unknown()).nullable().optional()
  })
  .strict()
  .refine((data) => Object.keys(data).length > 0, { message: 'At least one field must be provided' })

export const MergeResumeContextRequestSchema = z
  .record(z.string(), z.unknown())
  .refine((data) => Object.keys(data).length > 0, { message: 'At least one field must be provided' })

export const GetTasksQuerySchema = z
  .object({
    status: TaskStatusSchema.optional(),
    milestone_id: UuidSchema.optional(),
    parent_task_id: UuidSchema.optional()
  })
  .strict()

export const TaskIdParamsSchema = z.object({ id: UuidSchema })

// ---------------------------------------------------------------------------
// Notes
// ---------------------------------------------------------------------------

export const CreateNoteRequestSchema = z
  .object({
    project_id: UuidSchema,
    content: z.string().trim().min(1),
    type: NoteTypeSchema.optional(),
    summary: z.string().nullable().optional(),
    task_id: UuidSchema.nullable().optional(),
    milestone_id: UuidSchema.nullable().optional(),
    occurred_at: z.string().optional(),
    metadata: z.record(z.string(), z.unknown()).nullable().optional()
  })
  .strict()

export const UpdateNoteRequestSchema = z
  .object({
    content: z.string().trim().min(1).optional(),
    type: NoteTypeSchema.optional(),
    summary: z.string().nullable().optional(),
    task_id: UuidSchema.nullable().optional(),
    milestone_id: UuidSchema.nullable().optional(),
    occurred_at: z.string().optional(),
    metadata: z.record(z.string(), z.unknown()).nullable().optional()
  })
  .strict()
  .refine((data) => Object.keys(data).length > 0, { message: 'At least one field must be provided' })

export const NoteIdParamsSchema = z.object({ id: UuidSchema })

// ---------------------------------------------------------------------------
// Bundled export (mirrors CredentialSchemas pattern)
// ---------------------------------------------------------------------------

export const ProjectSchemas = {
  // Projects
  CreateProjectRequest: CreateProjectRequestSchema,
  UpdateProjectRequest: UpdateProjectRequestSchema,
  GetProjectsQuery: GetProjectsQuerySchema,
  ProjectIdParams: ProjectIdParamsSchema,
  ProjectSourceDealRef: ProjectSourceDealRefSchema,
  ProjectClientRef: ProjectClientRefSchema,

  // Milestones
  CreateMilestoneRequest: CreateMilestoneRequestSchema,
  UpdateMilestoneRequest: UpdateMilestoneRequestSchema,
  ProjectIdPathParams: ProjectIdPathParamsSchema,
  MilestoneIdParams: MilestoneIdParamsSchema,

  // Tasks
  CreateTaskRequest: CreateTaskRequestSchema,
  UpdateTaskRequest: UpdateTaskRequestSchema,
  MergeResumeContextRequest: MergeResumeContextRequestSchema,
  GetTasksQuery: GetTasksQuerySchema,
  TaskIdParams: TaskIdParamsSchema,

  // Notes
  CreateNoteRequest: CreateNoteRequestSchema,
  UpdateNoteRequest: UpdateNoteRequestSchema,
  NoteIdParams: NoteIdParamsSchema
}

// ---------------------------------------------------------------------------
// Inferred types
// ---------------------------------------------------------------------------

export type ProjectKind = z.infer<typeof ProjectKindSchema>
export type ProjectStatus = z.infer<typeof ProjectStatusSchema>
export type MilestoneStatus = z.infer<typeof MilestoneStatusSchema>
export type TaskStatus = z.infer<typeof TaskStatusSchema>
export type TaskType = z.infer<typeof TaskTypeSchema>
export type NoteType = z.infer<typeof NoteTypeSchema>
export type ChecklistItem = z.infer<typeof ChecklistItemSchema>
export type ProjectSourceDealRef = z.infer<typeof ProjectSourceDealRefSchema>
export type ProjectClientRef = z.infer<typeof ProjectClientRefSchema>
