using System;
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace JobTrackerApi.Migrations
{
    /// <summary>
    /// Phase 0 foundation change (2026-07-17):
    ///   - adds the Job entity (the opportunity), additively; nothing reads it yet,
    ///   - adds JobApplication.JobId (nullable FK) so the split can be completed later,
    ///   - adds JobApplication.SavedAt (when the user captured the job),
    ///   - makes JobApplication.DateApplied nullable so a job can be tracked before it is
    ///     applied to (see the Prospect stages in JobPipeline).
    ///
    /// HAND-EDITED after scaffolding. `dotnet ef migrations add` also emitted CreateTable for
    /// TrustedDevices / TwoFactorRecoveryCodes / UserSessions and AddColumn for the AspNetUsers
    /// Microsoft*/Totp* columns. Those were removed: they already exist in every real database,
    /// having been provisioned by the idempotent reconciler in StartupInitializationExtensions
    /// rather than by a migration, so the prior ModelSnapshot did not know about them and the
    /// scaffolder diffed them as missing. Re-creating them would fail with "table already
    /// exists" on any existing database. The reconciler still creates them on a fresh boot
    /// (CREATE TABLE IF NOT EXISTS), which is how this repo has always provisioned them.
    ///
    /// IX_JobApplications_OwnerUserId_IsDeleted_Status was dropped from this migration for the
    /// same reason: the reconciler applies it, and on MySQL it needs a Status(50) prefix length
    /// that this scaffolded DDL does not carry (see JobTrackerContext.OnModelCreating).
    ///
    /// See docs/decisions/ADR-002-job-application-model.md.
    /// </summary>
    public partial class AddJobEntityAndProspectStages : Migration
    {
        /// <inheritdoc />
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            // A job in a pre-application stage (Saved/Interested/Preparing) has no applied date.
            // On SQLite this is a table rebuild; EF carries over every column it knows about, and
            // all reconciler-added JobApplications columns are present in the model.
            migrationBuilder.AlterColumn<DateTime>(
                name: "DateApplied",
                table: "JobApplications",
                type: "TEXT",
                nullable: true,
                oldClrType: typeof(DateTime),
                oldType: "TEXT");

            migrationBuilder.AddColumn<int>(
                name: "JobId",
                table: "JobApplications",
                type: "INTEGER",
                nullable: true);

            migrationBuilder.AddColumn<DateTime>(
                name: "SavedAt",
                table: "JobApplications",
                type: "TEXT",
                nullable: false,
                defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));

            // Backfill: every pre-existing row is an applied job, so the best available estimate
            // of when it was captured is when it was applied. Without this each historic row keeps
            // the scaffolded 0001-01-01 sentinel, which would show as a bogus saved date and skew
            // the stage-entry maths that falls back to SavedAt.
            migrationBuilder.Sql("UPDATE JobApplications SET SavedAt = DateApplied WHERE DateApplied IS NOT NULL;");

            migrationBuilder.CreateTable(
                name: "Jobs",
                columns: table => new
                {
                    Id = table.Column<int>(type: "INTEGER", nullable: false)
                        .Annotation("Sqlite:Autoincrement", true),
                    OwnerUserId = table.Column<string>(type: "TEXT", nullable: true),
                    CompanyId = table.Column<int>(type: "INTEGER", nullable: false),
                    JobTitle = table.Column<string>(type: "TEXT", nullable: false),
                    Location = table.Column<string>(type: "TEXT", nullable: true),
                    JobUrl = table.Column<string>(type: "TEXT", nullable: true),
                    Description = table.Column<string>(type: "TEXT", nullable: true),
                    TranslatedDescription = table.Column<string>(type: "TEXT", nullable: true),
                    DescriptionLanguage = table.Column<string>(type: "TEXT", nullable: true),
                    ShortSummary = table.Column<string>(type: "TEXT", nullable: true),
                    Tags = table.Column<string>(type: "TEXT", nullable: true),
                    Deadline = table.Column<DateTime>(type: "TEXT", nullable: true),
                    Salary = table.Column<string>(type: "TEXT", nullable: true),
                    SalaryMin = table.Column<decimal>(type: "TEXT", nullable: true),
                    SalaryMax = table.Column<decimal>(type: "TEXT", nullable: true),
                    SalaryCurrency = table.Column<string>(type: "TEXT", nullable: true),
                    SalaryPeriod = table.Column<string>(type: "TEXT", nullable: true),
                    Source = table.Column<string>(type: "TEXT", nullable: true),
                    CountryCode = table.Column<string>(type: "TEXT", nullable: true),
                    SavedAt = table.Column<DateTime>(type: "TEXT", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Jobs", x => x.Id);
                    table.ForeignKey(
                        name: "FK_Jobs_Companies_CompanyId",
                        column: x => x.CompanyId,
                        principalTable: "Companies",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                });

            migrationBuilder.CreateIndex(
                name: "IX_JobApplications_JobId",
                table: "JobApplications",
                column: "JobId");

            migrationBuilder.CreateIndex(
                name: "IX_Jobs_CompanyId",
                table: "Jobs",
                column: "CompanyId");

            migrationBuilder.CreateIndex(
                name: "IX_Jobs_OwnerUserId",
                table: "Jobs",
                column: "OwnerUserId");

            migrationBuilder.AddForeignKey(
                name: "FK_JobApplications_Jobs_JobId",
                table: "JobApplications",
                column: "JobId",
                principalTable: "Jobs",
                principalColumn: "Id",
                onDelete: ReferentialAction.SetNull);
        }

        /// <inheritdoc />
        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropForeignKey(
                name: "FK_JobApplications_Jobs_JobId",
                table: "JobApplications");

            migrationBuilder.DropTable(
                name: "Jobs");

            migrationBuilder.DropIndex(
                name: "IX_JobApplications_JobId",
                table: "JobApplications");

            // Reverting DateApplied to NOT NULL requires every row to have one. Rows sitting in a
            // pre-application stage legitimately do not, so fall back to SavedAt before the ALTER
            // rather than letting it fail. Runs before SavedAt is dropped. This direction is lossy
            // by nature (an unapplied job gains an applied date) and exists for local rollback.
            migrationBuilder.Sql("UPDATE JobApplications SET DateApplied = SavedAt WHERE DateApplied IS NULL;");

            migrationBuilder.AlterColumn<DateTime>(
                name: "DateApplied",
                table: "JobApplications",
                type: "TEXT",
                nullable: false,
                defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
                oldClrType: typeof(DateTime),
                oldType: "TEXT",
                oldNullable: true);

            migrationBuilder.DropColumn(
                name: "SavedAt",
                table: "JobApplications");
        }
    }
}
