# -*- coding: utf-8 -*-
import json
import logging

import requests
from requests.exceptions import RequestException

from odoo import api, fields, models, _
from odoo.exceptions import UserError

_logger = logging.getLogger(__name__)


class JbEitCopyWizard(models.TransientModel):
    _name = 'jb.eit.copy.wizard'
    _description = 'Copy Timesheet Lines to EIT'

    line_ids = fields.Many2many(
        comodel_name='account.analytic.line',
        relation='jb_eit_copy_wizard_line_rel',
        column1='wizard_id',
        column2='line_id',
        string='Timesheet Lines',
        help='Timesheet lines to push to EIT.',
    )
    preview_html = fields.Html(
        string='Preview',
        readonly=True,
        help='Preview of lines that will be sent to EIT.',
    )

    # ------------------------------------------------------------------
    # Default: pre-populate from active_ids
    # ------------------------------------------------------------------

    @api.model
    def default_get(self, fields_list):
        res = super().default_get(fields_list)
        active_ids = self.env.context.get('active_ids', [])
        if active_ids:
            lines = self.env['account.analytic.line'].browse(active_ids)
            if 'line_ids' in fields_list:
                res['line_ids'] = [(6, 0, lines.ids)]
            if 'preview_html' in fields_list:
                res['preview_html'] = self._build_preview_html(lines)
        return res

    @api.model
    def _build_preview_html(self, lines):
        """Build an HTML preview table of lines to be sent."""
        pending = lines.filtered(lambda l: not l.eit_billing_id)
        already = lines.filtered(lambda l: l.eit_billing_id)

        rows = ''
        for line in pending:
            rows += (
                f'<tr>'
                f'<td>{line.date}</td>'
                f'<td>{line.employee_id.name or ""}</td>'
                f'<td>{line.project_id.name or ""}</td>'
                f'<td>{line.task_id.name or ""}</td>'
                f'<td>{line.name or ""}</td>'
                f'<td>{line.unit_amount:.2f}</td>'
                f'</tr>'
            )
        skipped_html = ''
        if already:
            skipped_html = (
                f'<p class="text-warning"><strong>'
                f'{len(already)} line(s) already have an EIT Billing ID and will be skipped.'
                f'</strong></p>'
            )
        if not rows:
            return (
                skipped_html
                + '<p class="text-danger">No new lines to send to EIT.</p>'
            )
        table = (
            '<table class="table table-sm table-bordered">'
            '<thead><tr>'
            '<th>Date</th><th>Employee</th><th>Project</th>'
            '<th>Task</th><th>Description</th><th>Hours</th>'
            '</tr></thead>'
            f'<tbody>{rows}</tbody>'
            '</table>'
        )
        return skipped_html + table

    # ------------------------------------------------------------------
    # Actions
    # ------------------------------------------------------------------

    def action_copy_to_eit(self):
        """POST pending timesheet lines to the EIT API."""
        self.ensure_one()
        ICP = self.env['ir.config_parameter'].sudo()
        eit_url = ICP.get_param('jb_timesheet.eit_api_url', default='')
        eit_token = ICP.get_param('jb_timesheet.eit_api_token', default='')

        if not eit_url:
            raise UserError(_(
                'EIT API URL is not configured. '
                'Please set jb_timesheet.eit_api_url in System Parameters.'
            ))

        pending_lines = self.line_ids.filtered(lambda l: not l.eit_billing_id)
        if not pending_lines:
            raise UserError(_('All selected lines already have an EIT Billing ID.'))

        headers = {'Content-Type': 'application/json'}
        if eit_token:
            headers['Authorization'] = f'Bearer {eit_token}'

        success_count = 0
        errors = []

        for line in pending_lines:
            payload = {
                'date': str(line.date),
                'duration': line.unit_amount,
                'description': line.name or '',
                'employee_eit_id': line.employee_id.eit_user_id or '',
                'client_eit_id': (
                    line.partner_id.eit_client_id if line.partner_id else ''
                ) or (
                    line.project_id.partner_id.eit_client_id
                    if line.project_id and line.project_id.partner_id else ''
                ),
                'project_eit_id': line.project_id.eit_project_id or '' if line.project_id else '',
                'task_name': line.task_id.name or '' if line.task_id else '',
                'notes_internal': line.notes_internal or '',
                'is_billable': line.is_billable,
            }
            try:
                response = requests.post(
                    eit_url,
                    data=json.dumps(payload),
                    headers=headers,
                    timeout=15,
                )
                response.raise_for_status()
                data = response.json()
                billing_id = (
                    data.get('billing_id')
                    or data.get('id')
                    or data.get('eit_billing_id')
                )
                if billing_id:
                    line.sudo().write({'eit_billing_id': str(billing_id)})
                    success_count += 1
                else:
                    errors.append(
                        f'Line {line.id}: response had no billing id field.'
                    )
                    _logger.warning(
                        'jb_timesheet: EIT response for line %s had no id: %s',
                        line.id, data,
                    )
            except RequestException as exc:
                msg = f'Line {line.id}: {exc}'
                errors.append(msg)
                _logger.error('jb_timesheet: EIT push failed for line %s: %s', line.id, exc)

        # Refresh preview
        self.preview_html = self._build_preview_html(self.line_ids)

        if errors:
            error_text = '\n'.join(errors)
            raise UserError(_(
                '%(count)s line(s) sent successfully.\n\nErrors:\n%(errors)s',
                count=success_count,
                errors=error_text,
            ))

        return {
            'type': 'ir.actions.client',
            'tag': 'display_notification',
            'params': {
                'title': _('EIT Push Complete'),
                'message': _(
                    '%(count)s timesheet line(s) successfully sent to EIT.',
                    count=success_count,
                ),
                'type': 'success',
                'sticky': False,
            },
        }
