import { ApiProperty } from '@nestjs/swagger';
import {
  IsInt,
  IsNotEmpty,
  IsOptional,
  IsArray,
  IsString,
  IsObject,
  ValidateNested,
  IsEnum,
} from 'class-validator';
import { Type } from 'class-transformer';
import { QuestionType } from 'src/common/enum/question-type.enum';
import { RegistrationLevelEnum } from 'src/common/enum/registration-level.enum';
import { ProgramQuestionInputDto, ProgramSectionInputDto } from './program-form-builder.dto';

// ─────────────────────────────────────────────────────────────────────────────
// Question-level update DTO
// ─────────────────────────────────────────────────────────────────────────────

/**
 * DTO for editing an existing question already mapped to the program.
 *
 * Provide `programQuestionId` (the ID in `hdb_program_question`) along with
 * whichever fields you want to change.  Any field omitted will remain unchanged.
 *
 * @example
 * {
 *   "programQuestionId": 1234,
 *   "label": "Updated question label",
 *   "config": { "isRequired": true, "maxCharacters": 200 },
 *   "displayOrder": 3
 * }
 */
export class UpdateQuestionItemDto {
  @ApiProperty({
    description: 'ID of the ProgramQuestion mapping record (hdb_program_question.id)',
    example: 1234,
  })
  @IsInt()
  @IsNotEmpty()
  programQuestionId: number;

  // ── Question fields (written to hdb_question) ──────────────────────────────

  @ApiProperty({
    description: 'Updated question label / text',
    example: 'Full Name (as per government ID)',
    required: false,
  })
  @IsOptional()
  @IsString()
  label?: string;

  @ApiProperty({
    description: 'Updated question type',
    example: 'text',
    enum: QuestionType,
    required: false,
  })
  @IsOptional()
  @IsEnum(QuestionType)
  type?: QuestionType;

  @ApiProperty({
    description: 'Updated question config (validation rules, etc.)',
    example: { isRequired: true, maxCharacters: 100 },
    required: false,
  })
  @IsOptional()
  @IsObject()
  config?: Record<string, any>;

  @ApiProperty({
    description: 'Updated option config (for dropdown / radio / checkbox / multiselect)',
    example: [{ value: 'yes', label: 'Yes' }, { value: 'no', label: 'No' }],
    required: false,
  })
  @IsOptional()
  @IsArray()
  optionConfig?: Record<string, any>[];

  @ApiProperty({
    description: 'Updated conditional config for the question',
    example: [{ field: 'programType', operator: 'in', values: ['HDB'] }],
    required: false,
  })
  @IsOptional()
  @IsObject()
  conditionalConfig?: Record<string, any>;

  // ── ProgramQuestion mapping fields ─────────────────────────────────────────

  @ApiProperty({
    description: 'Updated display order within the section',
    example: 2,
    required: false,
  })
  @IsOptional()
  @IsInt()
  displayOrder?: number;

}

// ─────────────────────────────────────────────────────────────────────────────
// Section-level update DTO
// ─────────────────────────────────────────────────────────────────────────────

/**
 * DTO for updating an existing section already part of the program form.
 *
 * - `sectionName`, `sectionDescription`, `displayOrder`, `conditionalConfig` — update section metadata
 * - `updateQuestions` — edit existing questions inside this section
 * - `addQuestions`    — add new questions to this section (same syntax as POST /program/form)
 * - `deleteQuestionIds` — programQuestionIds to soft-delete (removes mapping + question)
 *
 * @example
 * {
 *   "formSectionId": 41,
 *   "sectionName": "Attendee Information (updated)",
 *   "updateQuestions": [
 *     { "programQuestionId": 1234, "label": "Updated label", "displayOrder": 1 }
 *   ],
 *   "addQuestions": [
 *     { "masterQuestionId": 55 }
 *   ],
 *   "deleteQuestionIds": [1237, 1238]
 * }
 */
export class UpdateSectionItemDto {
  @ApiProperty({
    description: 'ID of the FormSection record (hdb_form_section.id) to update',
    example: 41,
  })
  @IsInt()
  @IsNotEmpty()
  formSectionId: number;

  // ── Section metadata updates (all optional) ────────────────────────────────

  @ApiProperty({
    description: 'New section name',
    example: 'Participant Information (revised)',
    required: false,
  })
  @IsOptional()
  @IsString()
  sectionName?: string;

  @ApiProperty({
    description: 'New section description',
    example: 'Please fill in your updated details',
    required: false,
  })
  @IsOptional()
  @IsString()
  sectionDescription?: string;

  @ApiProperty({
    description: 'New display order for the section',
    example: 2,
    required: false,
  })
  @IsOptional()
  @IsInt()
  displayOrder?: number;

  @ApiProperty({
    description: 'Updated conditional config for the section',
    example: { showIf: { questionId: 10, value: 'yes' } },
    required: false,
  })
  @IsOptional()
  @IsObject()
  conditionalConfig?: Record<string, any>;

  // ── Question operations ────────────────────────────────────────────────────

  @ApiProperty({
    description: 'Edit existing questions inside this section',
    type: [UpdateQuestionItemDto],
    required: false,
  })
  @IsOptional()
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => UpdateQuestionItemDto)
  updateQuestions?: UpdateQuestionItemDto[];

  @ApiProperty({
    description:
      'Add new questions to this section. Each entry follows the same rules as POST /program/form questions (masterQuestionId / templateQuestionId / label+type).',
    type: [ProgramQuestionInputDto],
    required: false,
    example: [
      { masterQuestionId: 55 },
      { label: 'Special dietary requirements', type: 'textarea', config: { isRequired: false } },
    ],
  })
  @IsOptional()
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => ProgramQuestionInputDto)
  addQuestions?: ProgramQuestionInputDto[];

  @ApiProperty({
    description:
      'ProgramQuestion IDs (hdb_program_question.id) to remove from this section. Both the mapping and the underlying Question record will be soft-deleted.',
    example: [1237, 1238],
    required: false,
  })
  @IsOptional()
  @IsArray()
  @IsInt({ each: true })
  deleteQuestionIds?: number[];
}

// ─────────────────────────────────────────────────────────────────────────────
// Main update DTO
// ─────────────────────────────────────────────────────────────────────────────

/**
 * DTO for PATCH /program/form – partial update of an existing program registration form.
 *
 * SUPPORTED OPERATIONS (all optional, can be combined in one request):
 * ─────────────────────────────────────────────────────────────────────
 * 1. **deleteSectionIds**    – Soft-delete entire sections (and all their questions)
 * 2. **updateSections**      – Edit section metadata, edit/add/delete questions within a section
 * 3. **addSections**         – Add brand-new sections (same syntax as POST /program/form sections)
 *
 * CONSTRAINTS:
 * ────────────
 * • `programId` must reference an existing program.
 * • A form must already exist for the program (at least one question mapped).
 * • `deleteSectionIds` and `formSectionId` inside `updateSections` must belong to the program.
 * • `deleteQuestionIds` inside `updateSections` must belong to the referenced section and program.
 * • Adding questions follows the same source rules as POST /program/form.
 *
 * @example Minimal – delete two questions from one section
 * {
 *   "programId": 1144,
 *   "updateSections": [
 *     {
 *       "formSectionId": 41,
 *       "deleteQuestionIds": [1237, 1238]
 *     }
 *   ]
 * }
 *
 * @example Full update
 * {
 *   "programId": 1144,
 *   "registrationLevel": "program",
 *   "deleteSectionIds": [45],
 *   "updateSections": [
 *     {
 *       "formSectionId": 41,
 *       "sectionName": "Participant Info (revised)",
 *       "updateQuestions": [
 *         { "programQuestionId": 1234, "label": "Full Name (as per ID)", "config": { "isRequired": true } }
 *       ],
 *       "addQuestions": [
 *         { "masterQuestionId": 55 }
 *       ],
 *       "deleteQuestionIds": [1237]
 *     }
 *   ],
 *   "addSections": [
 *     {
 *       "sectionName": "Travel Details",
 *       "sectionKey": "TRAVEL_DETAILS_V2",
 *       "displayOrder": 5,
 *       "questions": [
 *         { "masterQuestionId": 21 },
 *         { "masterQuestionId": 22 }
 *       ]
 *     }
 *   ]
 * }
 */
export class UpdateProgramFormDto {
  @ApiProperty({
    description:
      'IDs of FormSection records (hdb_form_section.id) to delete. All ProgramQuestion mappings and their underlying Question records within these sections will also be soft-deleted.',
    example: [45, 46],
    required: false,
  })
  @IsOptional()
  @IsArray()
  @IsInt({ each: true })
  deleteSectionIds?: number[];

  @ApiProperty({
    description:
      'Existing sections to update. Each entry identifies a section by formSectionId and can carry metadata changes plus question operations (update/add/delete).',
    type: [UpdateSectionItemDto],
    required: false,
  })
  @IsOptional()
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => UpdateSectionItemDto)
  updateSections?: UpdateSectionItemDto[];

  @ApiProperty({
    description:
      'Brand-new sections to add to the program form. Follows the same syntax as sections in POST /program/form.',
    type: [ProgramSectionInputDto],
    required: false,
    example: [
      {
        sectionName: 'Travel Details',
        sectionKey: 'TRAVEL_DETAILS_V2',
        displayOrder: 5,
        questions: [{ masterQuestionId: 21 }, { masterQuestionId: 22 }],
      },
    ],
  })
  @IsOptional()
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => ProgramSectionInputDto)
  addSections?: ProgramSectionInputDto[];
}

/**
 * Response DTO for the update program form endpoint.
 */
export class UpdateProgramFormResponseDto {
  @ApiProperty({ example: true })
  success: boolean;

  @ApiProperty({ example: 'Program form updated successfully' })
  message: string;

  @ApiProperty({
    example: {
      sectionsDeleted: 1,
      sectionsUpdated: 1,
      sectionsAdded: 1,
      questionsDeleted: 2,
      questionsUpdated: 1,
      questionsAdded: 2,
    },
  })
  data: {
    sectionsDeleted: number;
    sectionsUpdated: number;
    sectionsAdded: number;
    questionsDeleted: number;
    questionsUpdated: number;
    questionsAdded: number;
  };
}
