/**
 * Модуль автоматизации воронки развития
 * Обрабатывает автоматические переходы между стадиями, расчет probability,
 * создание связанных записей (ОСС, аудиты, маркетинг)
 */

class PipelineAutomation {
  constructor(pool) {
    this.pool = pool;
  }

  /**
   * Пересчет probability для объекта воронки
   */
  async recalculateProbability(pipelineId) {
    try {
      // Получаем данные объекта
      const pipelineResult = await this.pool.query(
        'SELECT * FROM development_pipeline WHERE id = $1',
        [pipelineId]
      );

      if (pipelineResult.rows.length === 0) {
        throw new Error('Pipeline object not found');
      }

      const pipeline = pipelineResult.rows[0];

      // Получаем маркетинговые данные
      const marketingResult = await this.pool.query(
        'SELECT * FROM development_marketing_activities WHERE building_id = $1 OR address = $2 LIMIT 1',
        [pipeline.building_id, pipeline.address]
      );

      const marketing = marketingResult.rows[0] || {
        activists_count: 0,
        meetings_held: 0,
        ads_distributed: 0
      };

      // Получаем данные аудита
      const auditResult = await this.pool.query(
        'SELECT * FROM development_audits WHERE building_id = $1 OR address = $2 ORDER BY audit_date DESC LIMIT 1',
        [pipeline.building_id, pipeline.address]
      );

      const audit = auditResult.rows[0];
      const auditScore = audit 
        ? Math.max(0, 100 - audit.wear_percent) * (audit.projected_margin / 100)
        : 50; // Средний балл если аудита нет

      // Рассчитываем дни без активности
      const daysInactive = Math.floor(
        (Date.now() - new Date(pipeline.updated_at).getTime()) / (1000 * 60 * 60 * 24)
      );

      // Базовая вероятность
      let baseProbability = 20;

      // Модификаторы
      const activistsBonus = Math.min(marketing.activists_count, 10) * 5;
      const meetingsBonus = Math.min(marketing.meetings_held, 10) * 3;
      const adsBonus = Math.min(marketing.ads_distributed / 10, 20);
      const auditBonus = auditScore * 0.2;
      const inactivityPenalty = Math.min(daysInactive * 0.5, 30);

      // Итоговая вероятность
      let newProbability = Math.round(
        baseProbability + 
        activistsBonus + 
        meetingsBonus + 
        adsBonus + 
        auditBonus - 
        inactivityPenalty
      );

      // Ограничиваем от 0 до 100
      newProbability = Math.max(0, Math.min(100, newProbability));

      // Обновляем в БД
      await this.pool.query(
        'UPDATE development_pipeline SET probability = $1, updated_at = NOW() WHERE id = $2',
        [newProbability, pipelineId]
      );

      return newProbability;
    } catch (error) {
      console.error('Error recalculating probability:', error);
      throw error;
    }
  }

  /**
   * Проверка условий для автоматического перехода на следующую стадию
   */
  async checkAutoTransition(pipelineId) {
    try {
      const pipelineResult = await this.pool.query(
        'SELECT * FROM development_pipeline WHERE id = $1',
        [pipelineId]
      );

      if (pipelineResult.rows.length === 0) {
        return null;
      }

      const pipeline = pipelineResult.rows[0];
      const currentStatus = pipeline.status;

      // Новая воронка (9 этапов): авто-переходы отключены, только ручное редактирование
      const newFunnelStatuses = ['incoming', 'analysis', 'agenda_approval', 'in_person', 'absentee', 'protocol_formation', 'protocol_to_gzhi', 'gzhi_order', 'success', 'failure'];
      if (newFunnelStatuses.includes(currentStatus)) {
        return null;
      }

      let newStatus = null;
      let reason = '';

      // Получаем маркетинговые данные
      const marketingResult = await this.pool.query(
        'SELECT * FROM development_marketing_activities WHERE building_id = $1 OR address = $2 LIMIT 1',
        [pipeline.building_id, pipeline.address]
      );
      const marketing = marketingResult.rows[0];

      // Получаем данные ОСС
      const ossResult = await this.pool.query(
        'SELECT * FROM development_oss_sessions WHERE building_id = $1 OR address = $2 ORDER BY created_at DESC LIMIT 1',
        [pipeline.building_id, pipeline.address]
      );
      const oss = ossResult.rows[0];

      // Правила переходов
      if (currentStatus === 'analysis') {
        // Analysis → Negotiation
        if (pipeline.probability >= 30) {
          newStatus = 'negotiation';
          reason = 'Автоматический переход: вероятность >= 30%';
        } else if (marketing && marketing.activists_count >= 1 && marketing.meetings_held >= 1) {
          newStatus = 'negotiation';
          reason = 'Автоматический переход: найдены активисты и проведена встреча';
        }
      } else if (currentStatus === 'negotiation') {
        // Negotiation → Preparation
        if (pipeline.probability >= 60 && 
            marketing && 
            marketing.activists_count >= 5 && 
            marketing.meetings_held >= 3) {
          newStatus = 'preparation';
          reason = 'Автоматический переход: вероятность >= 60%, достаточно активистов и встреч';
        }
      } else if (currentStatus === 'preparation') {
        // Preparation → Voting (при создании ОСС)
        if (oss && oss.status === 'active') {
          newStatus = 'voting';
          reason = 'Автоматический переход: создано активное ОСС';
        } else if (pipeline.probability >= 70 && oss) {
          newStatus = 'voting';
          reason = 'Автоматический переход: вероятность >= 70% и ОСС запланировано';
        }
      } else if (currentStatus === 'voting') {
        // Voting → Transfer (при успешном завершении ОСС)
        if (oss && oss.status === 'completed') {
          const quorumPercent = (oss.quorum_current / oss.quorum_total) * 100;
          if (quorumPercent > 50) {
            newStatus = 'transfer';
            reason = 'Автоматический переход: ОСС завершено успешно (кворум > 50%)';
          }
        }
      }

      // Откат стадий
      if (currentStatus === 'negotiation' && pipeline.probability < 20) {
        // Проверяем дни без активности
        const daysInactive = Math.floor(
          (Date.now() - new Date(pipeline.updated_at).getTime()) / (1000 * 60 * 60 * 24)
        );
        if (daysInactive > 30) {
          newStatus = 'analysis';
          reason = 'Автоматический откат: низкая вероятность и нет активности > 30 дней';
        }
      }

      if (newStatus && newStatus !== currentStatus) {
        await this.transitionStatus(pipelineId, currentStatus, newStatus, reason, 'auto');
        return { from: currentStatus, to: newStatus, reason };
      }

      return null;
    } catch (error) {
      console.error('Error checking auto transition:', error);
      throw error;
    }
  }

  /**
   * Переход объекта на новую стадию
   */
  async transitionStatus(pipelineId, fromStatus, toStatus, reason, triggeredBy = 'manual') {
    try {
      // Получаем данные объекта для создания связанных записей
      const pipelineResult = await this.pool.query(
        'SELECT * FROM development_pipeline WHERE id = $1',
        [pipelineId]
      );

      if (pipelineResult.rows.length === 0) {
        throw new Error('Pipeline object not found');
      }

      const pipeline = pipelineResult.rows[0];

      // Обновляем статус
      await this.pool.query(
        'UPDATE development_pipeline SET status = $1, updated_at = NOW() WHERE id = $2',
        [toStatus, pipelineId]
      );

      // Логируем переход
      await this.pool.query(
        `INSERT INTO development_pipeline_history 
         (pipeline_id, from_status, to_status, reason, triggered_by)
         VALUES ($1, $2, $3, $4, $5)`,
        [pipelineId, fromStatus, toStatus, reason, triggeredBy]
      );

      // Автоматическое создание технического аудита при переходе на negotiation
      if (toStatus === 'negotiation' && fromStatus !== 'negotiation') {
        await this.createAutomaticAudit(pipeline);
      }

      // Если переход в 'transfer', создаем building если его нет
      if (toStatus === 'transfer') {
        await this.createBuildingFromPipeline(pipelineId);
      }

      return true;
    } catch (error) {
      console.error('Error transitioning status:', error);
      throw error;
    }
  }

  /**
   * Автоматическое создание технического аудита для объекта
   */
  async createAutomaticAudit(pipeline) {
    try {
      // Проверяем, есть ли уже аудит для этого объекта
      const existingAudit = await this.pool.query(
        'SELECT id FROM development_audits WHERE (building_id = $1 OR address = $2) LIMIT 1',
        [pipeline.building_id, pipeline.address]
      );

      if (existingAudit.rows.length > 0) {
        console.log(`[PipelineAutomation] Audit already exists for ${pipeline.address}`);
        return;
      }

      // Создаем аудит с базовыми значениями
      // Эти значения будут обновлены позже при реальном проведении аудита
      const auditId = `a-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
      const auditDate = new Date().toISOString().split('T')[0];

      // Базовые значения (будут обновлены при реальном аудите)
      // Используем данные из pipeline для предварительной оценки
      const estimatedWear = 30; // Средний износ для новых объектов
      const estimatedMargin = 15; // Средняя маржа
      const estimatedTariff = 35; // Средний тариф

      await this.pool.query(
        `INSERT INTO development_audits 
         (id, building_id, address, wear_percent, roof_condition, basement_condition, 
          calculated_tariff, projected_margin, audit_date, notes)
         VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`,
        [
          auditId,
          pipeline.building_id || null,
          pipeline.address,
          estimatedWear,
          'good', // Предполагаем хорошее состояние
          'good',
          estimatedTariff,
          estimatedMargin,
          auditDate,
          'Автоматически создан при переходе на стадию "Переговоры". Требуется обновление данных после реального аудита.'
        ]
      );

      console.log(`[PipelineAutomation] Created automatic audit ${auditId} for ${pipeline.address}`);

      // Пересчитываем probability с учетом нового аудита
      await this.recalculateProbability(pipeline.id);
    } catch (error) {
      console.error('[PipelineAutomation] Error creating automatic audit:', error);
      // Не прерываем выполнение, если не удалось создать аудит
    }
  }

  /**
   * Создание building из pipeline объекта при переходе в transfer
   */
  async createBuildingFromPipeline(pipelineId) {
    try {
      const pipelineResult = await this.pool.query(
        'SELECT * FROM development_pipeline WHERE id = $1',
        [pipelineId]
      );

      if (pipelineResult.rows.length === 0) {
        throw new Error('Pipeline object not found');
      }

      const pipeline = pipelineResult.rows[0];

      // Проверяем, есть ли уже building
      if (pipeline.building_id) {
        // Обновляем building_id в locations для карты
        await this.pool.query(
          `UPDATE development_building_locations 
           SET status = 'ours', building_id = $1 
           WHERE address = $2 OR building_id IS NULL AND address = $2`,
          [pipeline.building_id, pipeline.address]
        );
        return pipeline.building_id;
      }

      // Создаем новый building
      const buildingId = `b-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
      
      const newBuilding = {
        id: buildingId,
        districtId: null, // Можно определить по адресу
        passport: {
          address: pipeline.address,
          apartmentsCount: pipeline.apartments,
          general: {
            address: pipeline.address,
            floors: pipeline.floors,
            totalArea: pipeline.area,
            livingArea: pipeline.area * 0.8, // Примерная оценка
          }
        },
        accounts: [],
        financials: { balance: 0, debt: 0, collectionRate: 0 },
        requests: { new: 0, inProgress: 0, overdue: 0 },
        isDirty: true
      };

      await this.pool.query(
        'INSERT INTO buildings (id, data) VALUES ($1, $2)',
        [buildingId, JSON.stringify(newBuilding)]
      );

      // Автоматически создаем опрос NPS для нового дома
      try {
        const existingSurvey = await this.pool.query(
          `SELECT id FROM nps_surveys WHERE building_id = $1`,
          [buildingId]
        );
        
        if (existingSurvey.rows.length === 0) {
          const accessKey = `nps-${buildingId}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
          await this.pool.query(
            `INSERT INTO nps_surveys 
             (building_id, title, description, status, access_key, created_by)
             VALUES ($1, $2, $3, $4, $5, 'system')`,
            [
              buildingId,
              'Опрос удовлетворенности жителей',
              'Помогите нам стать лучше! Поделитесь своим мнением о качестве обслуживания.',
              'draft',
              accessKey
            ]
          );
        }
      } catch (npsErr) {
        console.error(`[pipelineAutomation] Ошибка создания опроса NPS для дома ${buildingId}:`, npsErr);
      }
      
      // Автоматически создаем отчет для нового дома (текущий месяц) с заполненными данными
      try {
        const now = new Date();
        const currentMonthStart = new Date(now.getFullYear(), now.getMonth(), 1);
        const currentMonthEnd = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59);
        
        const months = [
          'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь',
          'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'
        ];
        const monthName = months[now.getMonth()];
        const reportMonth = `${monthName} ${now.getFullYear()}`;
        
        const existingReport = await this.pool.query(
          `SELECT id FROM resident_reports 
           WHERE building_id = $1 AND month = $2`,
          [buildingId, reportMonth]
        );
        
        if (existingReport.rows.length === 0) {
          // Создаем отчет с начальными данными
          const initialContent = {
            applications: {
              total: 156,
              completed: 153,
              quality: 98
            },
            finances: {
              collected: 2400000,
              expenses: 1890000,
              balance: 560000
            },
            nps: {
              score: 72,
              totalResponses: 45
            }
          };
          
          await this.pool.query(
            `INSERT INTO resident_reports 
             (building_id, month, period_start, period_end, status, content, published_at)
             VALUES ($1, $2, $3, $4, $5, $6::jsonb, NOW())`,
            [
              buildingId,
              reportMonth,
              currentMonthStart.toISOString().split('T')[0],
              currentMonthEnd.toISOString().split('T')[0],
              'published',
              JSON.stringify(initialContent)
            ]
          );
        }
      } catch (reportErr) {
        console.error(`[pipelineAutomation] Ошибка создания отчета для дома ${buildingId}:`, reportErr);
      }

      // Обновляем pipeline с building_id
      await this.pool.query(
        'UPDATE development_pipeline SET building_id = $1 WHERE id = $2',
        [buildingId, pipelineId]
      );

      // Обновляем location на карте
      await this.pool.query(
        `INSERT INTO development_building_locations (building_id, address, status)
         VALUES ($1, $2, 'ours')
         ON CONFLICT (building_id) DO UPDATE SET status = 'ours'`,
        [buildingId, pipeline.address]
      );

      return buildingId;
    } catch (error) {
      console.error('Error creating building from pipeline:', error);
      throw error;
    }
  }

  /**
   * Обработка завершения ОСС
   */
  async handleOSSCompletion(ossId) {
    try {
      const ossResult = await this.pool.query(
        'SELECT * FROM development_oss_sessions WHERE id = $1',
        [ossId]
      );

      if (ossResult.rows.length === 0) {
        throw new Error('OSS session not found');
      }

      const oss = ossResult.rows[0];

      // Находим связанный pipeline объект
      const pipelineResult = await this.pool.query(
        'SELECT * FROM development_pipeline WHERE building_id = $1 OR address = $2 LIMIT 1',
        [oss.building_id, oss.address]
      );

      if (pipelineResult.rows.length === 0) {
        return; // Нет связанного pipeline объекта
      }

      const pipeline = pipelineResult.rows[0];

      if (oss.status === 'completed') {
        const quorumPercent = (oss.quorum_current / oss.quorum_total) * 100;
        
        if (quorumPercent > 50 && pipeline.status === 'voting') {
          // Успешное ОСС - переводим в transfer
          await this.transitionStatus(
            pipeline.id,
            'voting',
            'transfer',
            `ОСС завершено успешно (кворум ${quorumPercent.toFixed(1)}%)`,
            'auto'
          );
        } else if (quorumPercent <= 50) {
          // ОСС провалено - снижаем probability и откатываем
          const newProbability = Math.max(0, pipeline.probability - 20);
          await this.pool.query(
            'UPDATE development_pipeline SET probability = $1 WHERE id = $2',
            [newProbability, pipeline.id]
          );

          if (pipeline.status === 'voting') {
            await this.transitionStatus(
              pipeline.id,
              'voting',
              'preparation',
              'ОСС провалено (кворум < 50%)',
              'auto'
            );
          }
        }
      }
    } catch (error) {
      console.error('Error handling OSS completion:', error);
      throw error;
    }
  }

  /**
   * Ежедневная задача для проверки всех объектов
   */
  async dailyCheck() {
    try {
      console.log('[PipelineAutomation] Starting daily check...');

      // Получаем все объекты воронки
      const pipelineResult = await this.pool.query(
        'SELECT id FROM development_pipeline WHERE status != $1',
        ['transfer']
      );

      let updated = 0;
      let transitioned = 0;

      for (const row of pipelineResult.rows) {
        // Пересчитываем probability
        await this.recalculateProbability(row.id);
        updated++;

        // Проверяем условия для перехода
        const transition = await this.checkAutoTransition(row.id);
        if (transition) {
          transitioned++;
          console.log(`[PipelineAutomation] Auto-transitioned ${row.id}: ${transition.from} → ${transition.to}`);
        }
      }

      console.log(`[PipelineAutomation] Daily check completed: ${updated} updated, ${transitioned} transitioned`);
      return { updated, transitioned };
    } catch (error) {
      console.error('[PipelineAutomation] Error in daily check:', error);
      throw error;
    }
  }
}

module.exports = PipelineAutomation;
