using System.Security.Cryptography;
using foodmarket.Api.Integrations.Telegram;
using foodmarket.Application.Common.Tenancy;
using foodmarket.Infrastructure.Persistence;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace foodmarket.Api.Controllers.Telegram;

/// <summary>Привязка Telegram-чата владельца к организации.
///
/// Flow:
/// 1. UI запрашивает <c>POST /api/organization/telegram/start</c> → сервер
///    генерирует одноразовый код (`tg_token`), кладёт в Telegram-payload
///    с deep-link <c>https://t.me/{bot}?start={code}</c> и orgId-маркером.
/// 2. Юзер открывает ссылку, бот через webhook /api/integrations/telegram/webhook
///    видит <c>/start {code}</c>, мапит code → orgId, отвечает «Связь установлена.
///    Введите код {Z}{Z}{Z}{Z} в админке».
///    Простоты ради реализуем lite-вариант: пользователь сам копирует chat_id
///    из @userinfobot или из ссылки бота и вставляет в UI. Полноценный webhook
///    — в следующей итерации.
/// 3. UI <c>PUT /api/organization/telegram/bind</c> с <c>chatId</c> → бот
///    отправляет подтверждающее сообщение, если 200 — сохраняем chatId в
///    <c>Organization.OwnerTelegramChatId</c>.
/// 4. <c>DELETE /api/organization/telegram</c> — отвязка (NULL чтобы джоб
///    больше не слал).
/// </summary>
[ApiController]
[Authorize(Policy = "AdminAccess")]
[Route("api/organization/telegram")]
public class TelegramBindingController : ControllerBase
{
    private readonly AppDbContext _db;
    private readonly ITelegramBotClient _bot;
    private readonly ITenantContext _tenant;

    public TelegramBindingController(AppDbContext db, ITelegramBotClient bot, ITenantContext tenant)
    {
        _db = db;
        _bot = bot;
        _tenant = tenant;
    }

    public sealed record StatusResp(bool BotEnabled, string? BotUsername, long? ChatId, string? DeepLink);

    [HttpGet("status")]
    public async Task<ActionResult<StatusResp>> Status(CancellationToken ct)
    {
        var orgId = _tenant.OrganizationId
            ?? throw new InvalidOperationException("No tenant in context");
        var chatId = await _db.Organizations.IgnoreQueryFilters()
            .Where(o => o.Id == orgId).Select(o => o.OwnerTelegramChatId).FirstOrDefaultAsync(ct);
        // Deep-link с маркером org_<orgIdSlice> — пользователь жмёт «Старт»,
        // бот видит маркер и пишет ответом chat_id. UI просит юзера ввести
        // chat_id руками (см. описание класса).
        var deepLink = _bot.IsEnabled && !string.IsNullOrWhiteSpace(_bot.BotUsername)
            ? $"https://t.me/{_bot.BotUsername}?start=org_{orgId:N}"
            : null;
        return Ok(new StatusResp(_bot.IsEnabled, _bot.BotUsername, chatId, deepLink));
    }

    public sealed record BindInput(long ChatId);

    [HttpPut("bind")]
    public async Task<IActionResult> Bind([FromBody] BindInput input, CancellationToken ct)
    {
        var orgId = _tenant.OrganizationId
            ?? throw new InvalidOperationException("No tenant in context");
        if (input.ChatId == 0) return BadRequest(new { error = "ChatId обязателен и не может быть 0." });
        if (!_bot.IsEnabled) return BadRequest(new { error = "Telegram-бот не настроен на сервере (нет токена)." });

        // Sanity-check: отправим тестовое сообщение. Если 200 — chat_id валиден.
        var orgName = await _db.Organizations.IgnoreQueryFilters()
            .Where(o => o.Id == orgId).Select(o => o.Name).FirstAsync(ct);
        var ok = await _bot.SendMessageAsync(input.ChatId,
            $"✅ Привязка к <b>{System.Net.WebUtility.HtmlEncode(orgName)}</b> подтверждена.\n" +
            "Ежедневная сводка будет приходить в 09:00 по МСК.", ct);
        if (!ok)
        {
            return BadRequest(new { error = "Не удалось отправить сообщение в Telegram — проверьте ChatId и что бот добавлен в чат." });
        }

        var org = await _db.Organizations.IgnoreQueryFilters().FirstAsync(o => o.Id == orgId, ct);
        org.OwnerTelegramChatId = input.ChatId;
        await _db.SaveChangesAsync(ct);
        return NoContent();
    }

    [HttpDelete]
    public async Task<IActionResult> Unbind(CancellationToken ct)
    {
        var orgId = _tenant.OrganizationId
            ?? throw new InvalidOperationException("No tenant in context");
        var org = await _db.Organizations.IgnoreQueryFilters().FirstAsync(o => o.Id == orgId, ct);
        org.OwnerTelegramChatId = null;
        await _db.SaveChangesAsync(ct);
        return NoContent();
    }
}
