import OSS from 'ali-oss'
import { readdirSync, statSync, readFileSync, existsSync, writeFileSync } from 'fs'
import { join, basename } from 'path'
import { fileURLToPath } from 'url'
import { createHash } from 'crypto'

const __dirname = fileURLToPath(new URL('.', import.meta.url))
const PROJECT_ROOT = join(__dirname, '..')
const CASE_DIR = join(PROJECT_ROOT, 'case-source')
const OUTPUT = join(PROJECT_ROOT, 'src/data/cases.ts')

// OSS 配置
const ossConfig = {
  accessKeyId: 'LTAI5tCfm2BwMkvwyyy7m7Pd',
  accessKeySecret: 'MImDwsY047Pugl8WfAETXKLwn1X6mJ',
  endpoint: 'oss-cn-shanghai.aliyuncs.com',
  bucket: 'schaeffler-dems',
  region: 'cn-shanghai',
}

const PHOTOS_PATH = 'photos'
const IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.webp']

const slugMap = {
  '10-景德镇陶川溪凯悦酒店': 'jingdezhen-taechuanxi-hyatt',
  '20-武汉茶林驿站': 'wuhan-chalin-station',
  '30-拉萨阿诺康巴酒店': 'lhasa-anuokangba-hotel',
  '40-温州嘉野酒店': 'wenzhou-jiaye-hotel',
  '50-美林别墅室内外': 'meilin-villa',
  '60-莫干山折折院': 'moganshan-zhezhe-courtyard',
  '70-景德镇建筑': 'jingdezhen-architecture',
}

function isImage(filename) {
  return IMAGE_EXTENSIONS.some((ext) => filename.toLowerCase().endsWith(ext))
}

function naturalSort(a, b) {
  return a.localeCompare(b, 'zh-CN-u-co-pinyin', { numeric: true })
}

function getOSSBaseUrl() {
  return `https://${ossConfig.bucket}.${ossConfig.endpoint}`
}

function getOSSKey(localPath) {
  // public/case/10-xxx/室内/01.jpg → photos/case/10-xxx/室内/01.jpg
  const relativePath = localPath.replace(/\\/g, '/').split('public/')[1]
  return `${PHOTOS_PATH}/${relativePath}`
}

function getOSSUrl(key) {
  return `${getOSSBaseUrl()}/${key}`
}

function getFileHash(filePath) {
  const buf = readFileSync(filePath)
  return createHash('md5').update(buf).digest('hex')
}

async function fileExistsOnOSS(client, key) {
  try {
    await client.head(key)
    return true
  } catch {
    return false
  }
}

async function uploadImagesToOSS(client, localDir, ossPrefix, uploaded) {
  const entries = readdirSync(localDir)
  const imageFiles = entries.filter((f) => !f.startsWith('.') && isImage(f) && statSync(join(localDir, f)).isFile())

  for (const file of imageFiles.sort(naturalSort)) {
    const localPath = join(localDir, file)
    const key = `${ossPrefix}/${file}`
    const url = getOSSUrl(key)

    // Check if already uploaded (skip if exists)
    const exists = await fileExistsOnOSS(client, key)
    if (exists) {
      uploaded.push({ localPath, key, url, status: 'skipped' })
      continue
    }

    try {
      await client.put(key, localPath, {
        headers: { 'x-oss-object-acl': 'public-read' },
      })
      uploaded.push({ localPath, key, url, status: 'uploaded' })
    } catch (err) {
      console.error(`  ✗ Failed: ${key} - ${err.message}`)
      uploaded.push({ localPath, key, url, status: 'failed' })
    }
  }
}

async function main() {
  const client = new OSS(ossConfig)
  const baseUrl = getOSSBaseUrl()

  console.log(`OSS Bucket: ${baseUrl}`)
  console.log(`Scanning: ${CASE_DIR}\n`)

  const folders = readdirSync(CASE_DIR)
    .filter((f) => statSync(join(CASE_DIR, f)).isDirectory() && !f.startsWith('.'))
    .sort((a, b) => parseInt(a) - parseInt(b))

  let totalUploaded = 0
  let totalSkipped = 0
  const cases = []

  for (const folder of folders) {
    const folderPath = join(CASE_DIR, folder)
    const ossCasePrefix = `${PHOTOS_PATH}/case/${folder}`

    const dashIdx = folder.indexOf('-')
    const sortNum = parseInt(folder.slice(0, dashIdx), 10)
    const title = folder.slice(dashIdx + 1)
    const slug = slugMap[folder] || `case-${sortNum}`

    console.log(`[${sortNum}] ${title}`)

    // Read description
    const txtPath = join(folderPath, '文字信息.txt')
    let description
    if (existsSync(txtPath)) {
      try {
        const raw = readFileSync(txtPath)
        description = new TextDecoder('gbk').decode(raw).trim()
      } catch {
        try { description = readFileSync(txtPath, 'utf-8').trim() } catch { /* skip */ }
      }
    }

    // Detect sub-folders
    const subFolders = readdirSync(folderPath)
      .filter((e) => statSync(join(folderPath, e)).isDirectory() && !e.startsWith('.'))
      .sort(naturalSort)

    // Get root-level images
    const rootEntries = readdirSync(folderPath)
      .filter((f) => !f.startsWith('.') && isImage(f) && statSync(join(folderPath, f)).isFile())
      .sort(naturalSort)

    const uploaded = []
    const categories = []
    let coverImage = ''

    if (subFolders.length > 0 && rootEntries.length === 0) {
      // Only sub-folders
      for (const sub of subFolders) {
        const subUploaded = []
        await uploadImagesToOSS(client, join(folderPath, sub), `${ossCasePrefix}/${sub}`, subUploaded)
        const images = subUploaded.filter((u) => u.status !== 'failed').map((u) => u.url)
        categories.push({ name: sub, images })
        uploaded.push(...subUploaded)
      }
    } else if (subFolders.length > 0 && rootEntries.length > 0) {
      // Both root images and sub-folders
      const rootUploaded = []
      await uploadImagesToOSS(client, folderPath, ossCasePrefix, rootUploaded)
      const rootImages = rootUploaded.filter((u) => u.status !== 'failed').map((u) => u.url)
      categories.push({ name: '室外', images: rootImages })
      uploaded.push(...rootUploaded)

      for (const sub of subFolders) {
        const subUploaded = []
        await uploadImagesToOSS(client, join(folderPath, sub), `${ossCasePrefix}/${sub}`, subUploaded)
        const images = subUploaded.filter((u) => u.status !== 'failed').map((u) => u.url)
        categories.push({ name: sub, images })
        uploaded.push(...subUploaded)
      }
    } else {
      // No sub-folders
      await uploadImagesToOSS(client, folderPath, ossCasePrefix, uploaded)
      const images = uploaded.filter((u) => u.status !== 'failed').map((u) => u.url)
      categories.push({ name: '', images })
    }

    coverImage = categories[0]?.images[0] || ''

    const uploadedCount = uploaded.filter((u) => u.status === 'uploaded').length
    const skippedCount = uploaded.filter((u) => u.status === 'skipped').length
    totalUploaded += uploadedCount
    totalSkipped += skippedCount

    console.log(`  Uploaded: ${uploadedCount}, Skipped: ${skippedCount}, Total: ${uploaded.length} images\n`)

    cases.push({ slug, title, sort: sortNum, description, coverImage, categories })
  }

  // Generate cases.ts
  const output = `// Auto-generated by scripts/upload-to-oss.mjs
// Do not edit manually - run "node scripts/upload-to-oss.mjs" to regenerate

import type { CaseData } from '@/types'

export const cases: CaseData[] = ${JSON.stringify(cases, null, 2)}
`

  writeFileSync(OUTPUT, output, 'utf-8')
  console.log(`\n✓ Generated ${cases.length} cases to ${OUTPUT}`)
  console.log(`✓ Total: ${totalUploaded} uploaded, ${totalSkipped} skipped`)
}

main().catch((err) => {
  console.error('Fatal error:', err)
  process.exit(1)
})
