import { MigrationInterface, QueryRunner } from 'typeorm';

// 드라이브 기능 — drive_folders / drive_files / project_folder_links 테이블 추가.
// - drive_folders: 사용자 소유 폴더 트리(adjacency list + materialized path)
// - drive_files: 오브젝트 스토리지 객체 메타(presign 업로드, status 로 완료 관리)
// - project_folder_links: 폴더를 프로젝트에 연동(공유), 권한(read/read-write)
export class AddDriveTables1782600000000 implements MigrationInterface {
  name = 'AddDriveTables1782600000000';

  public async up(queryRunner: QueryRunner): Promise<void> {
    // ===== drive_folders =====
    await queryRunner.query(
      `CREATE TABLE "drive_folders" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "name" character varying NOT NULL, "path" text NOT NULL, "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), "owner_id" uuid, "parent_id" uuid, CONSTRAINT "PK_drive_folders" PRIMARY KEY ("id"))`,
    );
    await queryRunner.query(
      `CREATE INDEX "IDX_drive_folders_owner" ON "drive_folders" ("owner_id")`,
    );
    await queryRunner.query(
      `CREATE INDEX "IDX_drive_folders_parent" ON "drive_folders" ("parent_id")`,
    );
    await queryRunner.query(
      `CREATE INDEX "IDX_drive_folders_path" ON "drive_folders" ("path")`,
    );

    // ===== drive_files =====
    await queryRunner.query(
      `CREATE TABLE "drive_files" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "name" character varying NOT NULL, "bucket" character varying NOT NULL, "object_key" character varying NOT NULL, "size" bigint NOT NULL, "mime" character varying NOT NULL, "kind" character varying NOT NULL, "status" character varying NOT NULL DEFAULT 'pending', "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), "owner_id" uuid, "folder_id" uuid, CONSTRAINT "PK_drive_files" PRIMARY KEY ("id"))`,
    );
    await queryRunner.query(
      `CREATE UNIQUE INDEX "IDX_drive_files_object_key" ON "drive_files" ("object_key")`,
    );
    await queryRunner.query(
      `CREATE INDEX "IDX_drive_files_owner" ON "drive_files" ("owner_id")`,
    );
    await queryRunner.query(
      `CREATE INDEX "IDX_drive_files_folder" ON "drive_files" ("folder_id")`,
    );
    await queryRunner.query(
      `CREATE INDEX "IDX_drive_files_status" ON "drive_files" ("status")`,
    );

    // ===== project_folder_links =====
    await queryRunner.query(
      `CREATE TABLE "project_folder_links" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "permission" character varying NOT NULL DEFAULT 'read', "created_at" TIMESTAMP NOT NULL DEFAULT now(), "project_id" uuid, "folder_id" uuid, "linked_by_id" uuid, CONSTRAINT "PK_project_folder_links" PRIMARY KEY ("id"))`,
    );
    await queryRunner.query(
      `CREATE INDEX "IDX_project_folder_links_project" ON "project_folder_links" ("project_id")`,
    );
    await queryRunner.query(
      `CREATE INDEX "IDX_project_folder_links_folder" ON "project_folder_links" ("folder_id")`,
    );
    // 한 폴더는 한 프로젝트에 한 번만 연동
    await queryRunner.query(
      `ALTER TABLE "project_folder_links" ADD CONSTRAINT "UQ_project_folder_link" UNIQUE ("project_id", "folder_id")`,
    );

    // ===== 외래키 =====
    await queryRunner.query(
      `ALTER TABLE "drive_folders" ADD CONSTRAINT "FK_drive_folders_owner" FOREIGN KEY ("owner_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
    );
    await queryRunner.query(
      `ALTER TABLE "drive_folders" ADD CONSTRAINT "FK_drive_folders_parent" FOREIGN KEY ("parent_id") REFERENCES "drive_folders"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
    );
    await queryRunner.query(
      `ALTER TABLE "drive_files" ADD CONSTRAINT "FK_drive_files_owner" FOREIGN KEY ("owner_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
    );
    await queryRunner.query(
      `ALTER TABLE "drive_files" ADD CONSTRAINT "FK_drive_files_folder" FOREIGN KEY ("folder_id") REFERENCES "drive_folders"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
    );
    await queryRunner.query(
      `ALTER TABLE "project_folder_links" ADD CONSTRAINT "FK_project_folder_links_project" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
    );
    await queryRunner.query(
      `ALTER TABLE "project_folder_links" ADD CONSTRAINT "FK_project_folder_links_folder" FOREIGN KEY ("folder_id") REFERENCES "drive_folders"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
    );
    await queryRunner.query(
      `ALTER TABLE "project_folder_links" ADD CONSTRAINT "FK_project_folder_links_linked_by" FOREIGN KEY ("linked_by_id") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE NO ACTION`,
    );
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    // 외래키 → 테이블 순서 역순 정리
    await queryRunner.query(
      `ALTER TABLE "project_folder_links" DROP CONSTRAINT "FK_project_folder_links_linked_by"`,
    );
    await queryRunner.query(
      `ALTER TABLE "project_folder_links" DROP CONSTRAINT "FK_project_folder_links_folder"`,
    );
    await queryRunner.query(
      `ALTER TABLE "project_folder_links" DROP CONSTRAINT "FK_project_folder_links_project"`,
    );
    await queryRunner.query(
      `ALTER TABLE "drive_files" DROP CONSTRAINT "FK_drive_files_folder"`,
    );
    await queryRunner.query(
      `ALTER TABLE "drive_files" DROP CONSTRAINT "FK_drive_files_owner"`,
    );
    await queryRunner.query(
      `ALTER TABLE "drive_folders" DROP CONSTRAINT "FK_drive_folders_parent"`,
    );
    await queryRunner.query(
      `ALTER TABLE "drive_folders" DROP CONSTRAINT "FK_drive_folders_owner"`,
    );

    await queryRunner.query(`DROP TABLE "project_folder_links"`);
    await queryRunner.query(`DROP TABLE "drive_files"`);
    await queryRunner.query(`DROP TABLE "drive_folders"`);
  }
}
