/**
 * Publikacja zatwierdzonego importu → rekord w `listings` + zdjęcia.
 */
import type { RowDataPacket } from 'mysql2'
import type { PoolConnection } from 'mysql2/promise'
import { randomUUID } from 'crypto'
import { getPool } from '@/lib/db'
import { findUserByEmail } from '@/lib/users'
import { slugifyListingBase } from '@/lib/listings'
import { saveListingImageBuffers } from '@/lib/listing-images-upload'
import { readImportImageBuffers } from '@/lib/import-images-upload'
import { downloadOlxOfferPhotoBuffers } from '@/lib/sync-olx-listing-images'
import { extractYearFromText } from '@/lib/olx-mapper'
import type { ListingCategoryId } from '@/data/listing-field-options'
import { fetchImportById } from '@/lib/listing-imports'

const DEFAULT_IMPORT_USER_EMAIL = 'import@twojalodka.pl'
const DEFAULT_PUBLICATION_DAYS = 180

async function uniqueSlug(conn: PoolConnection, candidate: string): Promise<string> {
  let slug = candidate.slice(0, 185)
  for (let i = 0; i < 12; i++) {
    const [rows] = await conn.execute<RowDataPacket[]>(
      'SELECT COUNT(*) AS c FROM listings WHERE slug = ? LIMIT 1',
      [slug],
    )
    if (Number(rows[0]?.c ?? 0) === 0) return slug
    slug = `${candidate.slice(0, 170)}-${randomUUID().slice(0, 8)}`
  }
  return `${candidate.slice(0, 120)}-${randomUUID()}`
}

/** Konto serwisowe — musi istnieć w `users` (utwórz ręcznie lub przez rejestrację). */
export async function resolveImportUserId(): Promise<string> {
  const email = (process.env.IMPORT_USER_EMAIL ?? DEFAULT_IMPORT_USER_EMAIL).trim().toLowerCase()
  const user = await findUserByEmail(email)
  if (!user) {
    throw new Error(
      `Brak konta importu (${email}). Utwórz użytkownika lub ustaw IMPORT_USER_EMAIL w .env.`,
    )
  }
  return user.id
}

export async function approveAndPublishImport(
  importId: string,
  adminUserId: string,
  options?: { categoryId?: ListingCategoryId },
): Promise<{ listingId: string; slug: string }> {
  const imp = await fetchImportById(importId)
  if (!imp) {
    const e = new Error('NOT_FOUND')
    ;(e as { code?: string }).code = 'NOT_FOUND'
    throw e
  }
  if (imp.status !== 'pending') {
    const e = new Error('INVALID_STATUS')
    ;(e as { code?: string }).code = 'INVALID_STATUS'
    throw e
  }

  const userId = await resolveImportUserId()
  const categoryId = options?.categoryId ?? (imp.suggestedCategoryId as ListingCategoryId) ?? 'power'
  const year = extractYearFromText(imp.title, imp.descriptionText)
  const baseSlug = slugifyListingBase(imp.title.slice(0, 70), year ? String(year) : '')

  const pool = getPool()
  const conn = await pool.getConnection()
  const listingId = randomUUID()

  try {
    await conn.beginTransaction()

    const slug = await uniqueSlug(conn, baseSlug)
    const durationDays = DEFAULT_PUBLICATION_DAYS
    const priceOnRequest = imp.priceOnRequest
    const pricePln = priceOnRequest ? null : imp.pricePln
    const offerType = imp.offerType ?? 'fixed'

    const specPayload = {
      import_source: imp.source,
      import_external_id: imp.externalId,
    }

    await conn.execute(
      `INSERT INTO listings (
        id, user_id, slug, status, category_id, manufacturer_text, title,
        year_built, price_pln, price_on_request, offer_type,
        condition_code, region_slug, country, location_text,
        description_text, notes_public,
        spec_json,
        publication_duration_days,
        published_at, expires_at,
        contact_name, contact_email, contact_phone,
        import_source, import_external_id, import_source_url
      ) VALUES (
        ?, ?, ?, 'active', ?, '', ?,
        ?, ?, ?, ?,
        ?, ?, 'Polska', ?,
        NULL, ?,
        CAST(? AS JSON),
        ?,
        NOW(3), DATE_ADD(NOW(3), INTERVAL ? DAY),
        ?, NULL, NULL,
        ?, ?, ?
      )`,
      [
        listingId,
        userId,
        slug,
        categoryId,
        imp.title.slice(0, 512),
        year,
        pricePln,
        priceOnRequest ? 1 : 0,
        offerType,
        imp.conditionCode,
        imp.regionSlug,
        imp.locationText,
        imp.descriptionText.slice(0, 65535),
        JSON.stringify(specPayload),
        durationDays,
        durationDays,
        (imp.sellerName ?? 'Sprzedawca OLX').slice(0, 255),
        imp.source,
        imp.externalId,
        imp.sourceUrl,
      ],
    )

    await conn.execute(
      `UPDATE listing_imports
       SET status = 'approved', listing_id = ?, reviewed_at = NOW(3), reviewed_by = ?
       WHERE id = ? AND status = 'pending'`,
      [listingId, adminUserId, importId],
    )

    await conn.commit()

    const buffers = await readImportImageBuffers(importId)
    let photoBuffers = buffers
    if (photoBuffers.length === 0 && imp.source === 'olx' && imp.externalId) {
      photoBuffers = await downloadOlxOfferPhotoBuffers(imp.externalId)
    }
    if (photoBuffers.length > 0) {
      await saveListingImageBuffers(listingId, photoBuffers, 'append')
    }

    return { listingId, slug }
  } catch (e) {
    await conn.rollback()
    throw e
  } finally {
    conn.release()
  }
}
