import { NextRequest, NextResponse } from 'next/server';

import { adminApiDisabledResponse, isAdminApiEnabled } from '@/lib/runtime/adminApi';
import type { FunnelDefinition, ScreenDefinition, TypographyVariant } from '@/lib/funnel/types';

/**
 * Нормализует TypographyVariant - удаляет объект если text пустой
 */
function normalizeTypography(typography: TypographyVariant | undefined): TypographyVariant | undefined {
  if (!typography) return undefined;
  
  // Если text пустой или только пробелы, удаляем весь объект
  if (!typography.text || typography.text.trim() === '') {
    return undefined;
  }
  
  return typography;
}

/**
 * Нормализует данные воронки перед сохранением в MongoDB
 * Удаляет пустые текстовые поля и лишние поля которые не соответствуют типам
 */
function normalizeFunnelData(funnelData: FunnelDefinition): FunnelDefinition {
  return {
    ...funnelData,
    screens: funnelData.screens.map((screen): ScreenDefinition => {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      const normalizedScreen: any = { ...screen };
      
      // Нормализуем subtitle (опциональное поле)
      if ('subtitle' in normalizedScreen) {
        const normalized = normalizeTypography(normalizedScreen.subtitle);
        if (normalized === undefined) {
          delete normalizedScreen.subtitle;
        } else {
          normalizedScreen.subtitle = normalized;
        }
      }
      
      // Нормализуем description (для info и soulmate экранов)
      // ⚠️ TypographyVariant НЕ содержит поле 'show', удаляем его если есть
      if ('description' in normalizedScreen) {
        const normalized = normalizeTypography(normalizedScreen.description);
        if (normalized === undefined) {
          delete normalizedScreen.description;
        } else {
          normalizedScreen.description = normalized;
          // Удаляем поле 'show' если оно есть (TypographyVariant не содержит его)
          if ('show' in normalizedScreen.description) {
            delete normalizedScreen.description.show;
          }
        }
      }
      
      // Удаляем специфичные для других шаблонов поля
      // Каждый шаблон должен содержать только свои поля
      switch (normalizedScreen.template) {
        case 'form':
          // fields нужно только для form экранов
          break;
        case 'email':
          // email имеет emailInput, а не fields
          if ('fields' in normalizedScreen) delete normalizedScreen.fields;
          if ('list' in normalizedScreen) delete normalizedScreen.list;
          break;
        case 'list':
          // list нужно только для list экранов
          if ('fields' in normalizedScreen) delete normalizedScreen.fields;
          break;
        case 'loaders':
          // progressbars нужно только для loaders
          if ('fields' in normalizedScreen) delete normalizedScreen.fields;
          if ('list' in normalizedScreen) delete normalizedScreen.list;
          break;
        default:
          // Для остальных шаблонов (info, date, coupon, soulmate) удаляем специфичные поля
          if ('fields' in normalizedScreen) delete normalizedScreen.fields;
          if ('list' in normalizedScreen) delete normalizedScreen.list;
          if ('progressbars' in normalizedScreen) delete normalizedScreen.progressbars;
          break;
      }
      
      // Нормализуем variants - добавляем пустой overrides если его нет
      if ('variants' in normalizedScreen && Array.isArray(normalizedScreen.variants)) {
        normalizedScreen.variants = normalizedScreen.variants.map((variant: { conditions?: unknown; overrides?: unknown }) => ({
          conditions: variant.conditions || [],
          overrides: variant.overrides || {},
        }));
      }
      
      // Удаляем variables из экранов, которые не поддерживают это поле
      // variables поддерживается только в info экранах
      if ('variables' in normalizedScreen && normalizedScreen.template !== 'info') {
        delete normalizedScreen.variables;
      }
      
      return normalizedScreen as ScreenDefinition;
    }),
  };
}

interface RouteParams {
  params: Promise<{
    id: string;
  }>;
}

// No normalization needed: we require `progressbars` for loaders

// GET /api/funnels/[id] - получить конкретную воронку
export async function GET(request: NextRequest, { params }: RouteParams) {
  if (!isAdminApiEnabled()) {
    return adminApiDisabledResponse();
  }

  try {
    const { id } = await params;
    const [{ default: connectMongoDB }, { default: FunnelModel }] = await Promise.all([
      import('@/lib/mongodb'),
      import('@/lib/models/Funnel'),
    ]);

    await connectMongoDB();

    const funnel = await FunnelModel.findById(id);
    
    if (!funnel) {
      return NextResponse.json(
        { error: 'Funnel not found' },
        { status: 404 }
      );
    }

    return NextResponse.json({
      _id: funnel._id,
      name: funnel.name,
      description: funnel.description,
      status: funnel.status,
      version: funnel.version,
      createdAt: funnel.createdAt,
      updatedAt: funnel.updatedAt,
      publishedAt: funnel.publishedAt,
      usage: funnel.usage,
      funnelData: funnel.funnelData
    });

  } catch (error) {
    console.error('GET /api/funnels/[id] error:', error);
    return NextResponse.json(
      { error: 'Failed to fetch funnel' },
      { status: 500 }
    );
  }
}

// PUT /api/funnels/[id] - обновить воронку
export async function PUT(request: NextRequest, { params }: RouteParams) {
  if (!isAdminApiEnabled()) {
    return adminApiDisabledResponse();
  }

  try {
    const { id } = await params;
    const [
      { default: connectMongoDB },
      { default: FunnelModel },
      { default: FunnelHistoryModel },
    ] = await Promise.all([
      import('@/lib/mongodb'),
      import('@/lib/models/Funnel'),
      import('@/lib/models/FunnelHistory'),
    ]);

    await connectMongoDB();

    const body = await request.json();
    const { name, description, funnelData, status, sessionId, actionDescription } = body;

    // Валидация
    if (funnelData && (!funnelData.meta || !funnelData.meta.id || !Array.isArray(funnelData.screens))) {
      return NextResponse.json(
        { error: 'Invalid funnel data structure' },
        { status: 400 }
      );
    }

    const funnel = await FunnelModel.findById(id);
    if (!funnel) {
      return NextResponse.json(
        { error: 'Funnel not found' },
        { status: 404 }
      );
    }

    // Сохраняем предыдущее состояние для истории
    const previousData = funnel.funnelData;

    // Обновляем поля
    if (name !== undefined) funnel.name = name;
    if (description !== undefined) funnel.description = description;
    
    // Логика версионирования:
    // - При сохранении (без смены статуса) - версия НЕ увеличивается
    // - При публикации - версия увеличивается и меняется статус
    const isPublishing = status === 'published' && funnel.status !== 'published';
    
    if (status !== undefined) funnel.status = status;
    if (funnelData !== undefined) {
      // Нормализуем данные перед сохранением (удаляем пустые текстовые поля)
      const normalizedData = normalizeFunnelData(funnelData as FunnelDefinition);
      funnel.funnelData = normalizedData;
      
      // Увеличиваем версию только при публикации
      if (isPublishing) {
        funnel.version += 1;
        funnel.publishedAt = new Date();
      }
    }

    funnel.lastModifiedBy = 'current-user'; // TODO: заменить на реального пользователя

    const savedFunnel = await funnel.save();

    // Создаем запись в истории, если обновлялась структура воронки
    if (funnelData && sessionId) {
      // Получаем текущий номер последовательности
      const lastHistoryEntry = await FunnelHistoryModel
        .findOne({ funnelId: id, sessionId })
        .sort({ sequenceNumber: -1 });
      
      const nextSequenceNumber = (lastHistoryEntry?.sequenceNumber || -1) + 1;
      
      // Нормализуем данные для истории
      const normalizedDataForHistory = normalizeFunnelData(funnelData as FunnelDefinition);
      
      await FunnelHistoryModel.create({
        funnelId: id,
        sessionId,
        funnelSnapshot: normalizedDataForHistory,
        actionType: status === 'published' ? 'publish' : 'update',
        sequenceNumber: nextSequenceNumber,
        description: actionDescription || 'Воронка обновлена',
        isBaseline: status === 'published',
        changeDetails: {
          action: 'update-funnel',
          previousValue: previousData,
          newValue: normalizedDataForHistory
        }
      });

      // Очищаем старые записи истории (оставляем 100)
      const KEEP_ENTRIES = 100;
      const entriesToDelete = await FunnelHistoryModel
        .find({ funnelId: id, sessionId })
        .sort({ sequenceNumber: -1 })
        .skip(KEEP_ENTRIES)
        .select('_id');
        
      if (entriesToDelete.length > 0) {
        const idsToDelete = entriesToDelete.map((entry: { _id: unknown }) => entry._id);
        await FunnelHistoryModel.deleteMany({ _id: { $in: idsToDelete } });
      }
    }

    return NextResponse.json({
      _id: savedFunnel._id,
      name: savedFunnel.name,
      description: savedFunnel.description,
      status: savedFunnel.status,
      version: savedFunnel.version,
      createdAt: savedFunnel.createdAt,
      updatedAt: savedFunnel.updatedAt,
      publishedAt: savedFunnel.publishedAt,
      usage: savedFunnel.usage,
      funnelData: savedFunnel.funnelData
    });

  } catch (error) {
    console.error('PUT /api/funnels/[id] error:', error);
    
    // Обработка ошибок валидации Mongoose
    if (error instanceof Error && error.name === 'ValidationError') {
      const validationError = error as Error & { errors: Record<string, { message: string }> };
      const details = [];
      
      // Собираем все ошибки валидации
      for (const field in validationError.errors) {
        const fieldError = validationError.errors[field];
        details.push(`${field}: ${fieldError.message}`);
      }
      
      return NextResponse.json(
        { 
          error: 'Ошибка валидации данных воронки',
          details: details.join('; ')
        },
        { status: 400 }
      );
    }
    
    // Обработка других ошибок
    const errorMessage = error instanceof Error ? error.message : 'Неизвестная ошибка';
    return NextResponse.json(
      { 
        error: 'Ошибка сохранения воронки',
        details: errorMessage
      },
      { status: 500 }
    );
  }
}

// DELETE /api/funnels/[id] - удалить воронку
export async function DELETE(request: NextRequest, { params }: RouteParams) {
  if (!isAdminApiEnabled()) {
    return adminApiDisabledResponse();
  }

  try {
    const { id } = await params;
    const [
      { default: connectMongoDB },
      { default: FunnelModel },
      { default: FunnelHistoryModel },
    ] = await Promise.all([
      import('@/lib/mongodb'),
      import('@/lib/models/Funnel'),
      import('@/lib/models/FunnelHistory'),
    ]);

    await connectMongoDB();

    const funnel = await FunnelModel.findById(id);
    if (!funnel) {
      return NextResponse.json(
        { error: 'Funnel not found' },
        { status: 404 }
      );
    }

    // Проверяем статус - опубликованные воронки нельзя удалять напрямую
    if (funnel.status === 'published') {
      return NextResponse.json(
        { error: 'Cannot delete published funnel. Archive it first.' },
        { status: 400 }
      );
    }

    // Удаляем воронку и всю связанную историю
    await Promise.all([
      FunnelModel.findByIdAndDelete(id),
      FunnelHistoryModel.deleteMany({ funnelId: id })
    ]);

    return NextResponse.json({ 
      message: 'Funnel deleted successfully' 
    });

  } catch (error) {
    console.error('DELETE /api/funnels/[id] error:', error);
    return NextResponse.json(
      { error: 'Failed to delete funnel' },
      { status: 500 }
    );
  }
}
