import { logger } from '../../utils/logger.js';
import { db } from '../../config/database.js';
import { emails, contacts } from '../../db/schema.js';
import { eq } from 'drizzle-orm';
import { jmapRequest, getMailboxes } from './client.js';

/**
 * Sync emails with a specific contact (bidirectional: both from and to)
 * ONLY syncs from Inbox and Sent mailboxes (no Archive, Trash, Drafts)
 * ONLY syncs recent emails (last 30 days by default)
 */
export const syncEmailsFromSender = async (
  jmapConfig,
  emailAccountId,
  contactId,
  senderEmail,
  options = {}
) => {
  const { limit = 50, daysBack = 30 } = options;

  try {
    logger.debug(`Synchronizácia emailov s kontaktom: ${senderEmail}`);

    const [contact] = await db
      .select({ companyId: contacts.companyId })
      .from(contacts)
      .where(eq(contacts.id, contactId))
      .limit(1);

    // Get Inbox and Sent mailboxes ONLY
    const mailboxes = await getMailboxes(jmapConfig);
    const inboxMailbox = mailboxes.find(m => m.role === 'inbox' || m.name === 'Inbox' || m.name === 'INBOX');
    const sentMailbox = mailboxes.find(m => m.role === 'sent' || m.name === 'Sent');

    if (!inboxMailbox) {
      logger.error('Priečinok Inbox nebol nájdený');
      throw new Error('Priečinok Inbox nebol nájdený');
    }

    logger.debug(`Používam priečinky: Inbox, Sent`);

    // Calculate date threshold (only emails from last X days)
    const dateThreshold = new Date();
    dateThreshold.setDate(dateThreshold.getDate() - daysBack);
    const dateThresholdISO = dateThreshold.toISOString();

    logger.debug(`Filtrovanie: posledných ${daysBack} dní pre ${senderEmail}`);

    // Query emails FROM the contact
    const queryFromResponse = await jmapRequest(jmapConfig, [
      [
        'Email/query',
        {
          accountId: jmapConfig.accountId,
          filter: {
            operator: 'AND',
            conditions: [
              { inMailbox: inboxMailbox.id },
              { from: senderEmail },
              { after: dateThresholdISO }
            ]
          },
          sort: [{ property: 'receivedAt', isAscending: false }],
          limit,
        },
        'query1',
      ],
    ]);

    const fromEmailIds = queryFromResponse.methodResponses[0][1].ids || [];
    logger.debug(`Nájdených ${fromEmailIds.length} emailov OD ${senderEmail}`);

    // Query emails TO the contact (from Sent folder if it exists)
    let toEmailIds = [];
    if (sentMailbox) {
      const queryToResponse = await jmapRequest(jmapConfig, [
        [
          'Email/query',
          {
            accountId: jmapConfig.accountId,
            filter: {
              operator: 'AND',
              conditions: [
                { inMailbox: sentMailbox.id },
                { to: senderEmail },
                { after: dateThresholdISO }
              ]
            },
            sort: [{ property: 'receivedAt', isAscending: false }],
            limit,
          },
          'query2',
        ],
      ]);

      toEmailIds = queryToResponse.methodResponses[0][1].ids || [];
      logger.debug(`Nájdených ${toEmailIds.length} emailov PRE ${senderEmail}`);
    }

    // Combine and deduplicate
    const emailIds = [...new Set([...fromEmailIds, ...toEmailIds])];
    logger.debug(`Celkovo unikátnych emailov: ${emailIds.length}`);

    if (emailIds.length === 0) {
      return { total: 0, saved: 0 };
    }

    // Fetch full email details
    const getResponse = await jmapRequest(jmapConfig, [
      [
        'Email/get',
        {
          accountId: jmapConfig.accountId,
          ids: emailIds,
          properties: [
            'id',
            'messageId',
            'threadId',
            'inReplyTo',
            'from',
            'to',
            'subject',
            'receivedAt',
            'textBody',
            'htmlBody',
            'bodyValues',
            'keywords',
          ],
          fetchTextBodyValues: true,
          fetchHTMLBodyValues: true,
        },
        'get1',
      ],
    ]);

    const emailsList = getResponse.methodResponses[0][1].list;
    let savedCount = 0;

    // Save emails to database
    for (const email of emailsList) {
      try {
        const fromEmail = email.from?.[0]?.email;
        const toEmail = email.to?.[0]?.email;
        const messageId = Array.isArray(email.messageId) ? email.messageId[0] : email.messageId;
        const inReplyTo = Array.isArray(email.inReplyTo) ? email.inReplyTo[0] : email.inReplyTo;
        const isRead = email.keywords && email.keywords['$seen'] === true;

        // Skip emails without from or to (malformed data)
        if (!fromEmail && !toEmail) {
          continue;
        }

        // VALIDATION: Email must belong to this contact
        // Email belongs to contact if:
        // - from === senderEmail (received email FROM contact)
        // - to === senderEmail (sent email TO contact)
        const belongsToContact =
          fromEmail?.toLowerCase() === senderEmail.toLowerCase() ||
          toEmail?.toLowerCase() === senderEmail.toLowerCase();

        if (!belongsToContact) {
          continue;
        }

        // Skip if already exists
        const [existing] = await db
          .select()
          .from(emails)
          .where(eq(emails.messageId, messageId))
          .limit(1);

        if (existing) {
          continue;
        }

        // Save email
        await db.insert(emails).values({
          emailAccountId,
          contactId,
          companyId: contact?.companyId || null,
          jmapId: email.id,
          messageId,
          threadId: email.threadId || messageId,
          inReplyTo: inReplyTo || null,
          from: fromEmail,
          to: toEmail,
          subject: email.subject || '(Bez predmetu)',
          body:
            email.bodyValues?.[email.textBody?.[0]?.partId]?.value ||
            email.bodyValues?.[email.htmlBody?.[0]?.partId]?.value ||
            '(Prázdna správa)',
          date: email.receivedAt ? new Date(email.receivedAt) : new Date(),
          isRead,
          sentByUserId: null, // Prijatý email, nie odpoveď
        });

        savedCount++;
      } catch (error) {
        logger.error(`Chyba pri ukladaní emailu ${email.messageId}`, error);
      }
    }

    logger.debug(`Synchronizovaných ${savedCount} nových emailov s ${senderEmail}`);
    return { total: emailsList.length, saved: savedCount };
  } catch (error) {
    logger.error('Nepodarilo sa synchronizovať emaily s kontaktom', error);
    throw error;
  }
};
