import os
import asyncio
import logging
import sys
import io

# Добавляем путь к корню проекта
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from trueconf import Bot, Dispatcher, Router, Message
from trueconf.types import FSInputFile

# Наши обработчики
from photo_processor import prepare_ad_photo, get_crop_coordinates
from utils.texts import (
    PHOTO_MAIN_MENU_TEXT,
    PHOTO_UNKNOWN_CMD_TEXT,
    PHOTO_PROCESSING_FACE_TEXT,
    PHOTO_UPLOADING_API_TEXT,
    photo_preview_ready,
    photo_success_published,
    photo_success_pending,
    photo_error_rejected,
    photo_error_already_pending,
    photo_cancel_text,
    photo_error_handling,
    EMOJI_DIGITS,
)

# Настройки
from config.config import *

# --- НАСТРОЙКА ЛОГИРОВАНИЯ ---
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[
        logging.FileHandler("photo_bot_log.txt", encoding="utf-8"),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

router = Router()
tc_bot = None

# 🧠 ПАМЯТЬ БОТА: Храним пути к фото, ожидающим подтверждения
# Пример: {'ds.krivochenko': {'path': '/tmp/orig_abc.jpg', 'coords': (100, 50, 300, 400)}}
pending_photos = {}


def _generate_preview(image_bytes: bytes, coords: tuple, size: int = 400) -> bytes | None:
    """Генерирует превью фото с кропом по координатам."""
    try:
        from PIL import Image
        img = Image.open(io.BytesIO(image_bytes))
        if img.mode != 'RGB':
            img = img.convert('RGB')
        
        x1, y1, x2, y2 = coords
        cropped = img.crop((x1, y1, x2, y2))
        
        # Ресайз до квадрата
        side = min(cropped.size[0], cropped.size[1])
        left = (cropped.size[0] - side) // 2
        top = (cropped.size[1] - side) // 2
        cropped = cropped.crop((left, top, left + side, top + side))
        
        preview = cropped.resize((size, size), Image.Resampling.LANCZOS)
        
        buf = io.BytesIO()
        preview.save(buf, format="JPEG", quality=85)
        buf.seek(0)
        return buf.getvalue()
    except Exception as e:
        logger.error(f"Ошибка генерации превью: {e}")
        return None


@router.message()
async def handle_message(msg: Message):
    global tc_bot
    
    # Определяем логин пользователя
    user_login = msg.from_user.id.split('@')[0] if '@' in msg.from_user.id else msg.from_user.id
    
    # Проверяем, вложение ли это
    is_attachment = hasattr(msg.type, "name") and msg.type.name == "ATTACHMENT"
    
    # =====================================================================
    # СЦЕНАРИЙ 1: Бот ждет ответа, и пользователь написал текст (Да/Нет)
    # =====================================================================
    if not is_attachment and user_login in pending_photos and msg.text:
        answer = msg.text.strip().lower()
        
        # Если согласен
        if answer in ["да", "yes", "+", "загрузить", "давай", "конечно"]:
            photo_data = pending_photos[user_login]
            original_path = photo_data['path']
            coords = photo_data['coords']
            
            await msg.answer(PHOTO_UPLOADING_API_TEXT)
            
            try:
                # Отправляем фото через API
                result = await asyncio.to_thread(
                    prepare_ad_photo, original_path, user_login
                )
                
                if result["success"]:
                    verdict = result.get("verdict")
                    if verdict == "published":
                        await msg.answer(photo_success_published())
                    elif verdict == "pending_moderation":
                        await msg.answer(photo_success_pending())
                    else:
                        # Успех, но вердикт другой — показываем сообщение
                        msg_text = result.get("message", "Фото обработано")
                        await msg.answer(f"✅ {msg_text}")
                else:
                    error = result.get("error", "Неизвестная ошибка")
                    if "уже есть фото" in error:
                        await msg.answer(photo_error_already_pending())
                    elif "отклонено" in error.lower() or "не прошел" in error.lower():
                        await msg.answer(photo_error_rejected(error))
                    else:
                        await msg.answer(f"❌ Ошибка: {error}")
            
            except Exception as e:
                logger.error(f"Ошибка отправки фото: {e}")
                await msg.answer(photo_error_handling())
            
            # Убираем за собой
            if os.path.exists(original_path):
                os.remove(original_path)
            del pending_photos[user_login]
            return
        
        # Если отказался
        elif answer in ["нет", "no", "-", "отмена"]:
            photo_data = pending_photos[user_login]
            original_path = photo_data['path']
            
            await msg.answer(photo_cancel_text())
            
            if os.path.exists(original_path):
                os.remove(original_path)
            del pending_photos[user_login]
            return
            
        # Если написал что-то непонятное
        else:
            await msg.answer(
                f"❓ Пожалуйста, нажмите:\n"
                f"1️⃣ — Подтвердить\n"
                f"2️⃣ — Вырезать заново\n\n"
                f"Или просто отправьте новое фото."
            )
            return
    
    # =====================================================================
    # СЦЕНАРИЙ 2: Пользователь прислал новую фотографию
    # =====================================================================
    if is_attachment:
        file_id = getattr(msg.content, "file_id", None)
        
        if not file_id:
            await msg.answer("❌ Не удалось получить файл. Попробуйте еще раз.")
            return

        await msg.answer(PHOTO_PROCESSING_FACE_TEXT)

        try:
            downloaded_file = await tc_bot.download_file_by_id(file_id)
            raw_path = downloaded_file
            
            # Читаем байты
            with open(raw_path, 'rb') as f:
                image_bytes = f.read()
            
            # Ищем лицо и получаем координаты
            coords = await asyncio.to_thread(get_crop_coordinates, image_bytes)
            
            if not coords:
                await msg.answer(
                    "❌ Лицо не найдено. Пожалуйста, сделайте фото анфас при хорошем освещении.\n\n"
                    f"{EMOJI_DIGITS['0']} — В главное меню"
                )
                if os.path.exists(raw_path):
                    os.remove(raw_path)
                return
            
            # Генерируем превью
            preview_bytes = _generate_preview(image_bytes, coords, size=400)
            
            if preview_bytes:
                # Сохраняем оригинал и координаты
                preview_path = f"/tmp/preview_{user_login}.jpg"
                with open(preview_path, 'wb') as f:
                    f.write(preview_bytes)
                
                # Сохраняем оригинал
                original_path = f"/tmp/orig_{user_login}.jpg"
                with open(original_path, 'wb') as f:
                    f.write(image_bytes)
                
                # Отправляем превью
                preview_doc = FSInputFile(preview_path, filename=f"preview_{user_login}.jpg")
                
                await msg.answer_photo(
                    preview_doc, preview_doc,
                    caption=photo_preview_ready()
                )
                
                # Сохраняем состояние
                pending_photos[user_login] = {
                    'path': original_path,
                    'coords': coords,
                    'preview_path': preview_path
                }
                logger.info(f"Фото подготовлено для {user_login}, координаты: {coords}")
            else:
                await msg.answer("❌ Ошибка обработки фото. Попробуйте снова.")
        
        except Exception as e:
            logger.error(f"Ошибка при работе с фото для {user_login}: {e}")
            await msg.answer(photo_error_handling())
        
        finally:
            # Удаляем оригинал TrueConf, но не превью (оно в pending_photos)
            if 'raw_path' in locals() and os.path.exists(raw_path):
                try: 
                    os.remove(raw_path)
                except: 
                    pass
        
        return

    # =====================================================================
    # СЦЕНАРИЙ 3: Дефолтное приветствие (если просто написали текст)
    # =====================================================================
    await msg.answer(PHOTO_MAIN_MENU_TEXT)

async def main():
    global tc_bot
    
    logger.info(f"Запуск фото-бота на сервере {TC_SERVER}...")
    
    dp = Dispatcher()
    dp.include_router(router)
    
    tc_bot = Bot.from_credentials(
        server=TC_SERVER, 
        username=TC_LOGIN, 
        password=TC_PASSWORD, 
        dispatcher=dp, 
        verify_ssl=False
    )
    
    await tc_bot.run()

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        logger.info("Бот остановлен пользователем.")
