import autoprefixer from 'autoprefixer'
import concat from 'gulp-concat'
import csso from 'gulp-csso'
import { deleteAsync } from 'del'
import gulp from 'gulp'
import gulpWebp from 'gulp-webp'
import imagemin, { mozjpeg, optipng, svgo } from 'gulp-imagemin'
import imageminAvif from 'imagemin-avif'
import order from 'gulp-order'
import plumber from 'gulp-plumber'
import postcss from 'gulp-postcss'
import pug from 'gulp-pug'
import rename from 'gulp-rename'
import uglify from 'gulp-uglify-es'
import * as dartSass from 'sass'
import gulpSass from 'gulp-sass'
import sourcemap from 'gulp-sourcemaps'
import svgstore from 'gulp-svgstore'
import sync from 'browser-sync'
import { nanoid } from 'nanoid'
import postcssUrl from 'postcss-url'
import inject from 'gulp-inject'
import newer from 'gulp-newer'
import twig from 'gulp-twig'
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
import { execSync } from 'child_process'
import dotenv from 'dotenv'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

// Загружаем переменные окружения из .env.local
const envPath = path.join(__dirname, '.env.local')
if (fs.existsSync(envPath)) {
  dotenv.config({ path: envPath })
  console.log('📝 Загружены настройки из .env.local')
} else {
  console.log('⚠️  Файл .env.local не найден. Запустите: gulp configInit')
}

const baseUrl = '.'
const pathCss = '..'
const searchId = Date.now()

// Конфигурация для разных шаблонизаторов
const settings = {
  templateEngine: process.env.TEMPLATE_ENGINE || 'pug', // 'pug' или 'twig'
  dataPath: 'src/data', // путь к JSON файлам с данными
  https: {
    enabled: process.env.HTTPS === 'true',
    keyPath: 'ssl/server.key',
    certPath: 'ssl/server.crt'
  },
  server: {
    port: process.env.PORT ? parseInt(process.env.PORT, 10) : 3000,
    host: process.env.HOST || 'localhost',
    open: process.env.OPEN_BROWSER === 'true',
    notify: process.env.BROWSER_SYNC_NOTIFY === 'true'
  }
}

// Выводим текущие настройки при запуске
console.log('⚙️  Текущие настройки:')
console.log(`   Шаблонизатор: ${settings.templateEngine}`)
console.log(`   HTTPS: ${settings.https.enabled ? 'включен' : 'выключен'}`)
console.log(`   Порт: ${settings.server.port}`)
console.log(`   Хост: ${settings.server.host}`)
console.log(`   Автооткрытие браузера: ${settings.server.open ? 'да' : 'нет'}`)
console.log(`   Уведомления: ${settings.server.notify ? 'да' : 'нет'}`)

// Функция для загрузки данных из JSON файлов
const loadData = () => {
  const dataPath = path.join(__dirname, settings.dataPath)
  let data = {}
  
  if (fs.existsSync(dataPath)) {
    const files = fs.readdirSync(dataPath).filter(file => file.endsWith('.json'))
    
    files.forEach(file => {
      const fileName = path.basename(file, '.json')
      const filePath = path.join(dataPath, file)
      
      try {
        const fileContent = fs.readFileSync(filePath, 'utf8')
        data[fileName] = JSON.parse(fileContent)
      } catch (error) {
        console.error(`Ошибка загрузки данных из ${file}:`, error.message)
      }
    })
  } else {
    console.log(`📁 Папка с данными не найдена: ${dataPath}`)
    console.log('💡 Запустите: gulp data для создания примера данных')
  }
  
  return data
}

const getImageSrcset = (path, format, params = '') => {
  return [1, 2]
    .map((dpr) => `${baseUrl}${path}@${dpr}x.${format}${params} ${dpr}x`)
    .join(', ')
}

const getImageMime = (format) => {
  switch (format) {
    case 'avif':
      return 'image/avif'
    case 'webp':
      return 'image/webp'
    case 'jpeg':
    case 'jpg':
      return 'image/jpeg'
    case 'png':
      return 'image/png'
    default:
      return null
  }
}

const sass = gulpSass(dartSass)

const clean = async () => {
  return await deleteAsync(['dist'])
}

const copy = () => {
  return gulp
    .src(
      [
        'src/fonts/**/*.{woff,woff2}',
        'src/img/**/*.{webm,webp,avif,jpg,jpeg,png,svg}',
        'src/favicon/**/*',
        'src/favicon.ico',
        'src/settings.js',
        'src/urls.json',
        'src/robots.txt'
      ],
      { base: 'src', encoding: false }
    )
    .pipe(gulp.dest('dist'))
}

const css = () => {
  return gulp
    .src('src/scss/index.scss')
    .pipe(plumber())
    .pipe(sourcemap.init())
    .pipe(sass.sync().on('error', sass.logError))
    .pipe(
      postcss([
        postcssUrl({
          url: (asset) => {
            if (asset.url.startsWith('/')) {
              return `${pathCss}${asset.url}?v=${searchId}`
            }
            return asset.url
          }
        }),
        autoprefixer({ remove: false })
      ])
    )
    .pipe(rename('style.css'))
    .pipe(sourcemap.write('.'))
    .pipe(gulp.dest('dist/css'))
    .pipe(sync.stream())
    .pipe(csso())
    .pipe(rename('style.min.css'))
    .pipe(gulp.dest('dist/css'))
}

const images = () => {
  return gulp
    .src('src/img/**/*.{png,jpg,jpeg,svg}', { base: 'src', encoding: false })
    .pipe(newer('dist'))
    .pipe(
      imagemin(
        [
          optipng({ optimizationLevel: 5 }),
          mozjpeg({ quality: 85, progressive: true }),
          svgo({
            plugins: [
              { name: 'removeViewBox', active: false },
              { name: 'removeXMLNS', active: false },
              { name: 'removeUnknownsAndDefaults', active: false }
            ]
          })
        ],
        { silent: true }
      )
    )
    .pipe(gulp.dest('dist'))
}

const webp = () => {
  return gulp
    .src('src/img/**/*.{png,jpg,jpeg}', { base: 'src', encoding: false })
    .pipe(newer({ dest: 'dist', ext: '.webp' }))
    .pipe(gulpWebp({ quality: 85 }))
    .pipe(gulp.dest('dist'))
}

const avif = () => {
  return gulp
    .src('src/img/**/*.{png,jpg,jpeg}', { base: 'src', encoding: false })
    .pipe(newer({ dest: 'dist', ext: '.avif' }))
    .pipe(imagemin([imageminAvif({ quality: 60 })], { silent: true }))
    .pipe(rename((path) => (path.extname = '.avif')))
    .pipe(gulp.dest('dist'))
}

const processImages = gulp.parallel(images, webp, avif)

const sprite = () => {
  return gulp
    .src('src/icons/**/*.svg')
    .pipe(svgstore({ inlineSvg: true }))
    .pipe(rename('sprite.svg'))
    .pipe(gulp.dest('dist/img'))
}

const injectSprite = () => {
  const spritePath = 'dist/img/sprite.svg'

  // Проверяем, существует ли файл спрайта
  if (!fs.existsSync(spritePath)) {
    console.log('⚠️  Спрайт не найден, пропускаем инъекцию')
    return Promise.resolve()
  }

  return gulp
    .src('dist/*.html')
    .pipe(
      inject(gulp.src(spritePath), {
        transform: (_, file) => {
          return file.contents.toString()
        }
      })
    )
    .pipe(gulp.dest('dist'))
}

// Инъекция спрайта только в конкретный файл
const injectSpriteToFile = (htmlFile) => {
  const spritePath = 'dist/img/sprite.svg'

  if (!fs.existsSync(spritePath) || !fs.existsSync(htmlFile)) {
    return Promise.resolve()
  }

  return gulp
    .src(htmlFile)
    .pipe(
      inject(gulp.src(spritePath), {
        transform: (_, file) => {
          return file.contents.toString()
        }
      })
    )
    .pipe(gulp.dest('dist'))
}

const jsCommon = () => {
  return gulp
    .src('src/js/common/*.js')
    .pipe(
      plumber({
        errorHandler(err) {
          console.error('JS Common Error:', err.toString())
          this.emit('end')
        }
      })
    )
    .pipe(order(['_utils.js', '*.js']))
    .pipe(sourcemap.init())
    .pipe(concat('script.js'))
    .pipe(sourcemap.write('.'))
    .pipe(gulp.dest('dist/js'))
}

const jsCommonMin = () => {
  return gulp
    .src('src/js/common/*.js')
    .pipe(
      plumber({
        errorHandler(err) {
          console.error('JS Common Min Error:', err.toString())
          this.emit('end')
        }
      })
    )
    .pipe(order(['_utils.js', '*.js']))
    .pipe(concat('script.min.js'))
    .pipe(uglify.default())
    .pipe(gulp.dest('dist/js'))
}

const jsVendor = () => {
  return gulp
    .src('src/js/vendor/*.js')
    .pipe(
      plumber({
        errorHandler(err) {
          console.error('JS Vendor Error:', err.toString())
          this.emit('end')
        }
      })
    )
    .pipe(concat('vendor.js'))
    .pipe(gulp.dest('dist/js'))
}

const jsVendorMin = () => {
  return gulp
    .src('src/js/vendor/*.js')
    .pipe(
      plumber({
        errorHandler(err) {
          console.error('JS Vendor Min Error:', err.toString())
          this.emit('end')
        }
      })
    )
    .pipe(concat('vendor.min.js'))
    .pipe(uglify.default())
    .pipe(gulp.dest('dist/js'))
}

const js = gulp.parallel(jsCommon, jsCommonMin, jsVendor, jsVendorMin)

// Простая обработка Pug шаблонов
const htmlPug = () => {
  const data = loadData()
  
  return gulp
    .src('src/pug/pages/**/*.pug')
    .pipe(plumber({
      errorHandler(err) {
        console.error('Pug Error:', err.toString())
        this.emit('end')
      }
    }))
    .pipe(
      pug({
        pretty: true,
        basedir: 'src/pug',
        locals: {
          baseUrl,
          searchId,
          getSrcset: getImageSrcset,
          getMime: getImageMime,
          ...data
        }
      })
    )
    .pipe(gulp.dest('dist'))
}

// Простая обработка Twig шаблонов
const htmlTwig = () => {
  const data = loadData()
  
  return gulp
    .src('src/twig/pages/**/*.twig')
    .pipe(plumber({
      errorHandler(err) {
        console.error('Twig Error:', err.toString())
        this.emit('end')
      }
    }))
    .pipe(
      twig({
        base: 'src/twig',
        data: {
          baseUrl,
          searchId,
          getSrcset: getImageSrcset,
          getMime: getImageMime,
          ...data
        },
        functions: [
          {
            name: 'getSrcset',
            func: getImageSrcset
          },
          {
            name: 'getMime', 
            func: getImageMime
          }
        ]
      })
    )
    .pipe(gulp.dest('dist'))
}

// Pug с инкрементальной сборкой
const htmlPugIncremental = () => {
  const data = loadData()
  
  return gulp
    .src('src/pug/pages/**/*.pug')
    .pipe(plumber({
      errorHandler(err) {
        console.error('Pug Error:', err.toString())
        this.emit('end')
      }
    }))
    .pipe(newer({
      dest: 'dist',
      ext: '.html'
    }))
    .pipe(
      pug({
        pretty: true,
        basedir: 'src/pug',
        locals: {
          baseUrl,
          searchId,
          getSrcset: getImageSrcset,
          getMime: getImageMime,
          ...data
        }
      })
    )
    .pipe(gulp.dest('dist'))
    .on('end', () => {
      console.log('📄 Обработаны только измененные Pug файлы')
    })
}

// Twig с инкрементальной сборкой
const htmlTwigIncremental = () => {
  const data = loadData()
  
  return gulp
    .src('src/twig/pages/**/*.twig')
    .pipe(plumber({
      errorHandler(err) {
        console.error('Twig Error:', err.toString())
        this.emit('end')
      }
    }))
    .pipe(newer({
      dest: 'dist',
      ext: '.html'
    }))
    .pipe(
      twig({
        base: 'src/twig',
        data: {
          baseUrl,
          searchId,
          getSrcset: getImageSrcset,
          getMime: getImageMime,
          ...data
        },
        functions: [
          {
            name: 'getSrcset',
            func: getImageSrcset
          },
          {
            name: 'getMime', 
            func: getImageMime
          }
        ]
      })
    )
    .pipe(gulp.dest('dist'))
    .on('end', () => {
      console.log('📄 Обработаны только измененные Twig файлы')
    })
}

// Универсальная функция для обработки HTML
const html = (incremental = false) => {
  if (settings.templateEngine === 'twig') {
    return incremental ? htmlTwigIncremental() : htmlTwig()
  } else {
    return incremental ? htmlPugIncremental() : htmlPug()
  }
}

// Создание SSL сертификатов для разработки
const createSSLCerts = (done) => {
  const sslDir = path.join(__dirname, 'ssl')
  const keyPath = path.join(sslDir, 'server.key')
  const certPath = path.join(sslDir, 'server.crt')
  
  if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {
    console.log('✅ SSL сертификаты уже существуют')
    done()
    return
  }
  
  if (!fs.existsSync(sslDir)) {
    fs.mkdirSync(sslDir, { recursive: true })
  }
  
  try {
    console.log('🔐 Создание SSL сертификатов для разработки...')
    
    execSync(`openssl genrsa -out ${keyPath} 2048`, { stdio: 'pipe' })
    
    const certCommand = `openssl req -new -x509 -key ${keyPath} -out ${certPath} -days 365 -subj "/C=RU/ST=Local/L=Local/O=Development/OU=Dev/CN=localhost"`
    execSync(certCommand, { stdio: 'pipe' })
    
    console.log('✅ SSL сертификаты успешно созданы')
    console.log('⚠️  Это сертификаты только для разработки!')
    
  } catch (error) {
    console.error('❌ Ошибка создания SSL сертификатов:')
    console.error('Убедитесь что OpenSSL установлен в системе')
  }
  
  done()
}

// Создание конфигурационного файла
const createHTTPSConfig = (done) => {
  const configPath = path.join(__dirname, '.env.local')
  
  if (!fs.existsSync(configPath)) {
    const envContent = `# Конфигурация для разработки
# Этот файл автоматически загружается при запуске gulp

# ===== ОСНОВНЫЕ НАСТРОЙКИ =====

# Включить HTTPS (true/false)
# После изменения нужно перезапустить gulp
HTTPS=false

# Шаблонизатор (pug/twig)  
# После изменения нужно перезапустить gulp
TEMPLATE_ENGINE=pug

# ===== НАСТРОЙКИ СЕРВЕРА =====

# Порт для разработки
PORT=3000

# Хост для разработки (localhost, 127.0.0.1, 0.0.0.0 для доступа извне)
HOST=localhost

# Автоматически открывать браузер при запуске (true/false)
OPEN_BROWSER=false

# Показывать уведомления BrowserSync (true/false)
BROWSER_SYNC_NOTIFY=false
`
    
    fs.writeFileSync(configPath, envContent)
    console.log('✅ Создан файл конфигурации: .env.local')
    console.log('📝 Теперь вы можете настроить параметры в .env.local')
  } else {
    console.log('ℹ️  Файл .env.local уже существует')
  }
  
  done()
}

// Функция для перезагрузки конфигурации
const reloadConfig = (done) => {
  const envPath = path.join(__dirname, '.env.local')
  if (fs.existsSync(envPath)) {
    // Очищаем старые значения
    delete process.env.TEMPLATE_ENGINE
    delete process.env.HTTPS
    delete process.env.PORT
    delete process.env.HOST
    delete process.env.OPEN_BROWSER
    delete process.env.BROWSER_SYNC_NOTIFY
    
    // Загружаем новые
    dotenv.config({ path: envPath, override: true })
    
    // Обновляем настройки
    settings.templateEngine = process.env.TEMPLATE_ENGINE || 'pug'
    settings.https.enabled = process.env.HTTPS === 'true'
    settings.server.port = process.env.PORT ? parseInt(process.env.PORT, 10) : 3000
    settings.server.host = process.env.HOST || 'localhost'
    settings.server.open = process.env.OPEN_BROWSER === 'true'
    settings.server.notify = process.env.BROWSER_SYNC_NOTIFY === 'true'
    
    console.log('🔄 Конфигурация перезагружена!')
    console.log('⚙️  Новые настройки:')
    console.log(`   Шаблонизатор: ${settings.templateEngine}`)
    console.log(`   HTTPS: ${settings.https.enabled ? 'включен' : 'выключен'}`)
    console.log(`   Порт: ${settings.server.port}`)
    console.log(`   Хост: ${settings.server.host}`)
    console.log('⚠️  Для применения HTTPS и смены шаблонизатора нужен перезапуск!')
  } else {
    console.log('❌ Файл .env.local не найден')
  }
  done()
}

// Задача для создания примера структуры данных
const createDataExample = (done) => {
  const dataDir = path.join(__dirname, 'src/data')
  
  if (!fs.existsSync(dataDir)) {
    fs.mkdirSync(dataDir, { recursive: true })
  }
  
  const exampleData = {
    site: {
      title: 'Мой сайт',
      description: 'Описание сайта',
      author: 'Автор'
    },
    navigation: [
      { title: 'Главная', url: '/' },
      { title: 'О нас', url: '/about' },
      { title: 'Контакты', url: '/contacts' }
    ]
  }
  
  fs.writeFileSync(
    path.join(dataDir, 'global.json'),
    JSON.stringify(exampleData, null, 2)
  )
  
  console.log('✅ Создан пример файла данных: src/data/global.json')
  done()
}

const refresh = (done) => {
  sync.reload()
  done()
}

// Обработка конкретного Pug файла
const processSinglePugFile = (filePath) => {
  const data = loadData()
  const relativePath = path.relative('src/pug/pages', filePath)
  const outputPath = path.join('dist', relativePath.replace('.pug', '.html'))
  
  console.log(`📄 Обработка файла: ${relativePath}`)
  
  return gulp
    .src(filePath)
    .pipe(plumber({
      errorHandler(err) {
        console.error('Pug Error:', err.toString())
        this.emit('end')
      }
    }))
    .pipe(
      pug({
        pretty: true,
        basedir: 'src/pug',
        locals: {
          baseUrl,
          searchId,
          getSrcset: getImageSrcset,
          getMime: getImageMime,
          ...data
        }
      })
    )
    .pipe(rename(path.basename(outputPath)))
    .pipe(gulp.dest(path.dirname(outputPath)))
}

// Обработка конкретного Twig файла
const processSingleTwigFile = (filePath) => {
  const data = loadData()
  const relativePath = path.relative('src/twig/pages', filePath)
  const outputPath = path.join('dist', relativePath.replace('.twig', '.html'))
  
  console.log(`📄 Обработка файла: ${relativePath}`)
  
  return gulp
    .src(filePath)
    .pipe(plumber({
      errorHandler(err) {
        console.error('Twig Error:', err.toString())
        this.emit('end')
      }
    }))
    .pipe(
      twig({
        base: 'src/twig',
        data: {
          baseUrl,
          searchId,
          getSrcset: getImageSrcset,
          getMime: getImageMime,
          ...data
        },
        functions: [
          {
            name: 'getSrcset',
            func: getImageSrcset
          },
          {
            name: 'getMime', 
            func: getImageMime
          }
        ]
      })
    )
    .pipe(rename(path.basename(outputPath)))
    .pipe(gulp.dest(path.dirname(outputPath)))
}

// Сервер с поддержкой HTTPS
const server = () => {
  let serverConfig = {
    server: 'dist/',
    notify: settings.server.notify,
    open: settings.server.open,
    cors: true,
    ui: false,
    port: settings.server.port,
    host: settings.server.host
  }
  
  if (settings.https.enabled) {
    const keyPath = path.join(__dirname, settings.https.keyPath)
    const certPath = path.join(__dirname, settings.https.certPath)
    
    if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {
      serverConfig.https = {
        key: keyPath,
        cert: certPath
      }
      console.log('🔒 Запуск сервера с HTTPS')
      console.log(`📍 https://${serverConfig.host}:${serverConfig.port}`)
    } else {
      console.log('⚠️  HTTPS включен, но сертификаты не найдены')
      console.log('Запустите: gulp ssl для создания сертификатов')
    }
  } else {
    console.log('🌐 Запуск HTTP сервера')
    console.log(`📍 http://${serverConfig.host}:${serverConfig.port}`)
  }

  sync.init(serverConfig)

  // Умное наблюдение за страницами
  if (settings.templateEngine === 'twig') {
    // Отслеживание изменений в страницах Twig
    const twigWatcher = gulp.watch('src/twig/pages/**/*.twig')
    twigWatcher.on('change', (filePath) => {
      console.log(`🔄 Изменен файл: ${path.relative(__dirname, filePath)}`)
      return gulp.series(
        () => processSingleTwigFile(filePath),
        refresh
      )()
    })
    
    // Наблюдение за общими файлами - полная пересборка
    gulp.watch(['src/twig/**/*.twig', '!src/twig/pages/**/*.twig'], gulp.series(() => html(false), injectSprite, refresh))
  } else {
    // Отслеживание изменений в страницах Pug
    const pugWatcher = gulp.watch('src/pug/pages/**/*.pug')
    pugWatcher.on('change', (filePath) => {
      console.log(`🔄 Изменен файл: ${path.relative(__dirname, filePath)}`)
      return gulp.series(
        () => processSinglePugFile(filePath),
        refresh
      )()
    })
    
    // Наблюдение за общими файлами - полная пересборка  
    gulp.watch(['src/pug/**/*.pug', '!src/pug/pages/**/*.pug'], gulp.series(() => html(false), injectSprite, refresh))
  }
  
  // Наблюдение за данными - полная пересборка
  gulp.watch('src/data/**/*.json', gulp.series(() => html(false), injectSprite, refresh))
  
  // Наблюдение за спрайтами - полная пересборка с инъекцией
  gulp.watch('src/icons/**/*.svg', gulp.series(sprite, () => html(false), injectSprite, refresh))
  
  // Остальные файлы
  gulp.watch('src/scss/**/*.scss', gulp.series(css))
  gulp.watch('src/js/**/*.js', gulp.series(js, refresh))
  gulp.watch('src/img/**/*.{png,jpg,jpeg,svg}', gulp.series(processImages, refresh))
}

// Экспорт задач
export const build = gulp.series(
  clean,
  copy,
  css,
  js,
  processImages,
  sprite,
  () => html(false),
  injectSprite
)

export const dev = gulp.series(build, server)
export const data = createDataExample
export const ssl = createSSLCerts
export const configInit = createHTTPSConfig
export const configReload = reloadConfig

// HTTPS команды
export const devSSL = gulp.series(
  (done) => { 
    settings.https.enabled = true
    done() 
  },
  ssl,
  build, 
  server
)

// Команды с выбором шаблонизатора
export const buildPug = gulp.series(
  (done) => { settings.templateEngine = 'pug'; done() },
  build
)

export const buildTwig = gulp.series(
  (done) => { settings.templateEngine = 'twig'; done() },
  build
)

export const devPug = gulp.series(
  (done) => { settings.templateEngine = 'pug'; done() },
  build,
  server
)

export const devTwig = gulp.series(
  (done) => { settings.templateEngine = 'twig'; done() },
  build,
  server
)

export const devPugSSL = gulp.series(
  (done) => { 
    settings.templateEngine = 'pug'
    settings.https.enabled = true
    done() 
  },
  ssl,
  build,
  server
)

export const devTwigSSL = gulp.series(
  (done) => { 
    settings.templateEngine = 'twig'
    settings.https.enabled = true
    done() 
  },
  ssl,
  build,
  server
)