/**
 * Landing Page Deployment Model
 *
 * Durable queue record for publishing a landing page to a hosting provider — modelled
 * on SocialMediaPublication (Social Media OS). The collection itself is the queue: the
 * hostingDeployWorker ticks periodically, claims `queued` deployments (respecting
 * nextAttemptAt backoff and a workerLockedAt claim), bundles the page into a standalone
 * artifact, uploads it via the provider adapter, and records the result.
 *
 * Entirely additive: replaces nothing. The landing-page generator's existing in-memory
 * job flow is untouched; this is a separate, restart-safe deployment queue.
 */

import mongoose, { Schema, Document } from 'mongoose';
import { HostingProvider } from './HostingConnection';

export type DeploymentStatus =
  | 'draft'
  | 'queued'
  | 'bundling'
  | 'deploying'
  | 'live'
  | 'failed'
  | 'cancelled';

export interface IDeploymentError {
  code?: string;
  message?: string;
  at?: Date;
}

/**
 * Frozen copy of everything that goes live, captured when the deployment is enqueued.
 * The worker bundles from this — never from the live artifact — so the published page
 * is a static version that later platform edits cannot change.
 */
export interface IDeploymentSnapshot {
  /** Absolute path of the frozen artifact directory */
  dir?: string;
  /** Id the generator keyed its image URLs on (needed to rewrite them in the bundle) */
  artifactId?: string;
  capturedAt?: Date;
  /** Fingerprint of the frozen files + settings, used to detect unpublished changes */
  contentHash?: string;
  fileCount?: number;
  /** Publish-time copy of the page settings the bundler reads (SEO, tracking, embeds…) */
  pageSettings?: Record<string, any>;
  /** Publish-time copy of the manual colour / CTA customisation */
  themeCustomization?: Record<string, any> | null;
}

export interface ILandingPageDeployment extends Document {
  companyId: string;
  createdBy: string;         // owning admin — isolation anchor
  landingPageId: string;     // id of the page inside LandingPageContentOS.pages[]
  landingPageName?: string;

  provider: HostingProvider;
  connectionRef: string;     // HostingConnection _id (snapshot at creation)

  status: DeploymentStatus;
  attemptCount: number;
  nextAttemptAt?: Date | null;
  workerLockedAt?: Date | null;

  // Per-deploy options captured at enqueue time
  customDomain?: string;
  snapshot?: IDeploymentSnapshot;

  // Result
  deployUrl?: string;
  providerDeployId?: string;
  bundleHash?: string;
  fileCount?: number;
  publishedAt?: Date;

  lastError?: IDeploymentError;
  errorHistory: IDeploymentError[];

  createdAt: Date;
  updatedAt: Date;
}

const DeploymentErrorSchema = new Schema<IDeploymentError>({
  code: { type: String },
  message: { type: String },
  at: { type: Date },
}, { _id: false });

const DeploymentSnapshotSchema = new Schema<IDeploymentSnapshot>({
  dir: { type: String },
  artifactId: { type: String },
  capturedAt: { type: Date },
  contentHash: { type: String },
  fileCount: { type: Number },
  pageSettings: { type: Schema.Types.Mixed },
  themeCustomization: { type: Schema.Types.Mixed, default: null },
}, { _id: false });

const LandingPageDeploymentSchema = new Schema<ILandingPageDeployment>({
  companyId: { type: String, required: true, index: true },
  createdBy: { type: String, required: true, index: true },
  landingPageId: { type: String, required: true, index: true },
  landingPageName: { type: String },

  provider: {
    type: String,
    enum: ['sftp', 'ftp', 'netlify', 'vercel', 'cloudflare-pages', 'github-pages', 's3', 'wordpress'],
    required: true,
  },
  connectionRef: { type: String, required: true },

  status: {
    type: String,
    enum: ['draft', 'queued', 'bundling', 'deploying', 'live', 'failed', 'cancelled'],
    default: 'queued',
    index: true,
  },
  attemptCount: { type: Number, default: 0 },
  nextAttemptAt: { type: Date, default: null },
  workerLockedAt: { type: Date, default: null },

  customDomain: { type: String },
  snapshot: { type: DeploymentSnapshotSchema, default: null },

  deployUrl: { type: String },
  providerDeployId: { type: String },
  bundleHash: { type: String },
  fileCount: { type: Number },
  publishedAt: { type: Date },

  lastError: { type: DeploymentErrorSchema, default: null },
  errorHistory: { type: [DeploymentErrorSchema], default: [] },
}, {
  timestamps: true,
});

// Worker scan index — claim queued jobs whose backoff has elapsed.
LandingPageDeploymentSchema.index({ status: 1, nextAttemptAt: 1 });
LandingPageDeploymentSchema.index({ companyId: 1, landingPageId: 1, createdAt: -1 });

export const LandingPageDeployment =
  mongoose.models.LandingPageDeployment ||
  mongoose.model<ILandingPageDeployment>('LandingPageDeployment', LandingPageDeploymentSchema);
