import json
import logging
from odoo import http, fields
from odoo.http import request
from odoo.addons.encoach_api.controllers.base import (
    jwt_required, _json_response, _error_response, _get_json_body, _paginate
)

_logger = logging.getLogger(__name__)


class EncoachAiCourseController(http.Controller):

    # ------------------------------------------------------------------
    # POST /api/ai-course/english/create
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/english/create', type='http', auth='none',
                methods=['POST'], csrf=False)
    @jwt_required
    def create_english(self, **kw):
        try:
            body = _get_json_body()
            cefr_level = body.get('cefr_level')
            if not cefr_level:
                return _error_response('cefr_level is required', 400)

            user = request.env.user.sudo()
            gap_profile_id = body.get('gap_profile_id')

            GapProfile = request.env['encoach.gap.profile'].sudo()
            if gap_profile_id:
                gap_profile = GapProfile.browse(int(gap_profile_id))
                if not gap_profile.exists():
                    return _error_response('Gap profile not found', 404)
            else:
                gap_profile = GapProfile.search(
                    [('student_id', '=', user.id)],
                    order='created_at desc', limit=1,
                )
                if not gap_profile:
                    gap_profile = GapProfile.create({
                        'student_id': user.id,
                        'source_type': 'exam',
                        'skill_gaps': json.dumps([]),
                        'topic_weaknesses': json.dumps([]),
                    })

            brief = {
                'skill_gaps': json.loads(gap_profile.skill_gaps or '[]'),
                'topic_weaknesses': json.loads(gap_profile.topic_weaknesses or '[]'),
                'cefr_level': cefr_level,
            }

            Log = request.env['encoach.ai.generation.log'].sudo()
            log = Log.create({
                'student_id': user.id,
                'course_type': 'general_english',
                'status': 'pending_review',
                'brief': json.dumps(brief),
                'attempts': 1,
            })

            return _json_response({
                'log_id': log.id,
                'status': log.status,
                'brief': brief,
            }, 201)

        except Exception as e:
            _logger.exception('create_english failed')
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # POST /api/ai-course/ielts/create
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/ielts/create', type='http', auth='none',
                methods=['POST'], csrf=False)
    @jwt_required
    def create_ielts(self, **kw):
        try:
            body = _get_json_body()
            skill = body.get('skill')
            target_band = body.get('target_band')

            if not skill:
                return _error_response('skill is required', 400)
            if not target_band:
                return _error_response('target_band is required', 400)

            valid_skills = ('listening', 'reading', 'writing', 'speaking')
            if skill not in valid_skills:
                return _error_response(
                    f'skill must be one of: {", ".join(valid_skills)}', 400,
                )

            brief = {
                'skill': skill,
                'target_band': float(target_band),
                'custom_instructions': body.get('brief', ''),
            }

            Log = request.env['encoach.ai.ielts.generation.log'].sudo()
            log = Log.create({
                'skill': skill,
                'status': 'format_check',
                'brief': json.dumps(brief),
                'attempts': 1,
            })

            return _json_response({
                'log_id': log.id,
                'status': log.status,
                'skill': log.skill,
            }, 201)

        except Exception as e:
            _logger.exception('create_ielts failed')
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # GET /api/ai-course/<int:course_id>/quality
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/<int:course_id>/quality', type='http',
                auth='none', methods=['GET'], csrf=False)
    @jwt_required
    def quality(self, course_id, **kw):
        try:
            Log = request.env['encoach.ai.generation.log'].sudo()
            log = Log.browse(course_id)
            if not log.exists():
                return _error_response('Generation log not found', 404)

            return _json_response({
                'status': log.status,
                'readability_score': 0.0,
                'cefr_alignment': log.status in ('quality_check', 'approved'),
                'grammar_issues': [],
                'attempts': log.attempts,
            })

        except Exception as e:
            _logger.exception('quality check failed')
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # POST /api/ai-course/<int:course_id>/approve
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/<int:course_id>/approve', type='http',
                auth='none', methods=['POST'], csrf=False)
    @jwt_required
    def approve(self, course_id, **kw):
        try:
            Log = request.env['encoach.ai.generation.log'].sudo()
            log = Log.browse(course_id)
            if not log.exists():
                return _error_response('Generation log not found', 404)

            if log.status == 'approved':
                return _error_response('Already approved', 400)

            log.write({
                'status': 'approved',
                'approved_by': request.env.user.id,
            })

            return _json_response({'approved': True})

        except Exception as e:
            _logger.exception('approve failed')
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # POST /api/ai-course/<int:course_id>/reject
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/<int:course_id>/reject', type='http',
                auth='none', methods=['POST'], csrf=False)
    @jwt_required
    def reject(self, course_id, **kw):
        try:
            body = _get_json_body()

            Log = request.env['encoach.ai.generation.log'].sudo()
            log = Log.browse(course_id)
            if not log.exists():
                return _error_response('Generation log not found', 404)

            reason = body.get('reason', '')
            can_retry = log.attempts < 3

            if can_retry:
                log.write({
                    'status': 'generating',
                    'attempts': log.attempts + 1,
                    'error_log': reason or log.error_log,
                })
            else:
                log.write({
                    'status': 'rejected',
                    'error_log': reason or log.error_log,
                })

            return _json_response({
                'rejected': True,
                'can_retry': can_retry,
            })

        except Exception as e:
            _logger.exception('reject failed')
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # GET /api/ai-course/<int:course_id>/validation
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/<int:course_id>/validation', type='http',
                auth='none', methods=['GET'], csrf=False)
    @jwt_required
    def validation(self, course_id, **kw):
        try:
            IeltsLog = request.env['encoach.ai.ielts.generation.log'].sudo()
            ielts_log = IeltsLog.browse(course_id)
            if ielts_log.exists():
                fmt_result = {}
                band_result = {}
                try:
                    fmt_result = json.loads(ielts_log.format_check_result or '{}')
                except (json.JSONDecodeError, TypeError):
                    pass
                try:
                    band_result = json.loads(ielts_log.band_check_result or '{}')
                except (json.JSONDecodeError, TypeError):
                    pass

                overall_passed = bool(
                    ielts_log.format_check_result and ielts_log.band_check_result
                )
                return _json_response({
                    'type': 'ielts',
                    'validation_results': {
                        'format_check_result': fmt_result,
                        'band_check_result': band_result,
                    },
                    'overall_passed': overall_passed,
                })

            Log = request.env['encoach.ai.generation.log'].sudo()
            log = Log.browse(course_id)
            if not log.exists():
                return _error_response('Generation log not found', 404)

            validation_results = {
                'status': log.status,
                'quality_passed': log.status in ('approved', 'pending_review'),
                'attempts': log.attempts,
            }

            return _json_response({
                'type': 'english',
                'validation_results': validation_results,
                'overall_passed': log.status == 'approved',
            })

        except Exception as e:
            _logger.exception('validation check failed')
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # GET /api/ai-course/<int:course_id>
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/<int:course_id>', type='http', auth='none',
                methods=['GET'], csrf=False)
    @jwt_required
    def get_course(self, course_id, **kw):
        try:
            Log = request.env['encoach.ai.generation.log'].sudo()
            log = Log.browse(course_id)
            if not log.exists():
                IeltsLog = request.env['encoach.ai.ielts.generation.log'].sudo()
                ielts = IeltsLog.browse(course_id)
                if not ielts.exists():
                    return _error_response('Course/log not found', 404)
                return _json_response({
                    'id': ielts.id,
                    'type': 'ielts',
                    'skill': ielts.skill or '',
                    'status': ielts.status or '',
                    'review_status': getattr(ielts, 'review_status', ''),
                    'created_at': ielts.create_date.isoformat() if ielts.create_date else '',
                })

            brief = {}
            try:
                brief = json.loads(log.brief or '{}')
            except (json.JSONDecodeError, TypeError):
                pass

            return _json_response({
                'id': log.id,
                'type': 'general_english',
                'status': log.status or '',
                'course_type': log.course_type or '',
                'brief': brief,
                'attempts': log.attempts,
                'student_id': log.student_id.id if log.student_id else None,
                'created_at': log.create_date.isoformat() if log.create_date else '',
            })

        except Exception as e:
            _logger.exception('get_course failed')
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # GET /api/ai-course/<int:course_id>/tracks
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/<int:course_id>/tracks', type='http', auth='none',
                methods=['GET'], csrf=False)
    @jwt_required
    def get_tracks(self, course_id, **kw):
        try:
            Log = request.env['encoach.ai.generation.log'].sudo()
            log = Log.browse(course_id)
            if not log.exists():
                return _error_response('Course not found', 404)

            generated = {}
            try:
                generated = json.loads(log.generated_content or '{}')
            except (json.JSONDecodeError, TypeError):
                pass

            tracks = []
            modules = generated.get('modules', [])
            for i, mod in enumerate(modules):
                tracks.append({
                    'index': i,
                    'title': mod.get('title', f'Module {i+1}'),
                    'skill': mod.get('skill', ''),
                    'status': 'completed' if i == 0 else 'locked',
                    'progress': 100 if i == 0 else 0,
                })

            if not tracks:
                tracks = [{
                    'index': 0,
                    'title': 'Course content pending generation',
                    'skill': '',
                    'status': 'pending',
                    'progress': 0,
                }]

            return _json_response({'tracks': tracks})

        except Exception as e:
            _logger.exception('get_tracks failed')
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # GET /api/ai-course/english/taxonomy
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/english/taxonomy', type='http', auth='none',
                methods=['GET'], csrf=False)
    @jwt_required
    def english_taxonomy(self, **kw):
        try:
            taxonomy = {
                'skills': ['reading', 'listening', 'writing', 'speaking', 'grammar', 'vocabulary'],
                'cefr_levels': ['A1', 'A2', 'B1', 'B2', 'C1', 'C2'],
                'content_types': ['lesson', 'exercise', 'assessment', 'review'],
                'topic_domains': [
                    'daily_life', 'work', 'education', 'travel',
                    'technology', 'environment', 'health', 'culture',
                ],
            }

            Taxonomy = request.env.get('encoach.taxonomy.domain')
            if Taxonomy:
                domains = Taxonomy.sudo().search([])
                if domains:
                    taxonomy['topic_domains'] = [
                        {'id': d.id, 'name': d.name, 'description': getattr(d, 'description', '')}
                        for d in domains
                    ]

            return _json_response(taxonomy)

        except Exception as e:
            _logger.exception('english_taxonomy failed')
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # POST /api/ai-course/examiner-review
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/examiner-review', type='http', auth='none',
                methods=['POST'], csrf=False)
    @jwt_required
    def examiner_review(self, **kw):
        try:
            body = _get_json_body()
            log_id = body.get('log_id')
            action = body.get('action')
            examiner_notes = body.get('examiner_notes', '')

            if not log_id:
                return _error_response('log_id is required', 400)
            if action not in ('approve', 'reject', 'revise'):
                return _error_response('action must be approve, reject, or revise', 400)

            IeltsLog = request.env['encoach.ai.ielts.generation.log'].sudo()
            log = IeltsLog.browse(int(log_id))
            if not log.exists():
                return _error_response('Log not found', 404)

            status_map = {
                'approve': 'approved',
                'reject': 'rejected',
                'revise': 'revision_needed',
            }

            log.write({
                'review_status': status_map[action],
                'examiner_id': request.env.user.id,
                'examiner_notes': examiner_notes,
                'reviewed_at': fields.Datetime.now(),
            })

            return _json_response({'status': status_map[action], 'log_id': log_id})

        except Exception as e:
            _logger.exception('examiner_review failed')
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # GET /api/ai-course/review-queue
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/review-queue', type='http', auth='none',
                methods=['GET'], csrf=False)
    @jwt_required
    def review_queue(self, **kw):
        try:
            body = _get_json_body() if request.httprequest.content_length else {}
            page = int(kw.get('page', 1))
            size = int(kw.get('size', 20))

            Resource = request.env['encoach.resource'].sudo()
            domain = [('ai_generated', '=', True), ('review_status', '=', 'pending')]
            total = Resource.search_count(domain)
            resources = Resource.search(domain, limit=size, offset=(page - 1) * size, order='create_date desc')

            return _json_response({
                'total': total,
                'page': page,
                'size': size,
                'items': [r.to_api_dict() for r in resources],
            })
        except Exception as e:
            _logger.exception('review_queue failed')
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # POST /api/ai-course/review/<int:resource_id>
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/review/<int:resource_id>', type='http', auth='none',
                methods=['POST'], csrf=False)
    @jwt_required
    def review_resource(self, resource_id, **kw):
        try:
            body = _get_json_body()
            action = body.get('action')
            notes = body.get('notes', '')

            if action not in ('approve', 'reject'):
                return _error_response('action must be approve or reject', 400)

            Resource = request.env['encoach.resource'].sudo()
            resource = Resource.browse(resource_id)
            if not resource.exists():
                return _error_response('Resource not found', 404)

            vals = {
                'review_status': 'approved' if action == 'approve' else 'rejected',
                'approved': action == 'approve',
            }
            resource.write(vals)

            return _json_response({'status': vals['review_status'], 'resource_id': resource_id})
        except Exception as e:
            _logger.exception('review_resource failed')
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # GET /api/ai-course/ielts-review-queue
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/ielts-review-queue', type='http', auth='none',
                methods=['GET'], csrf=False)
    @jwt_required
    def ielts_review_queue(self, **kw):
        try:
            page = int(kw.get('page', 1))
            size = int(kw.get('size', 20))

            Log = request.env['encoach.ai.ielts.generation.log'].sudo()
            domain = [('review_status', '=', 'pending_review')]
            total = Log.search_count(domain)
            logs = Log.search(domain, limit=size, offset=(page - 1) * size, order='create_date desc')

            items = []
            for log in logs:
                items.append({
                    'id': log.id,
                    'skill': log.skill or '',
                    'band_target': log.band_target if hasattr(log, 'band_target') else 0,
                    'review_status': log.review_status,
                    'created_at': log.create_date.isoformat() if log.create_date else '',
                })

            return _json_response({
                'total': total,
                'page': page,
                'size': size,
                'items': items,
            })
        except Exception as e:
            _logger.exception('ielts_review_queue failed')
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # POST /api/ai-course/ielts-review/<int:log_id>
    # ------------------------------------------------------------------
    @http.route('/api/ai-course/ielts-review/<int:log_id>', type='http', auth='none',
                methods=['POST'], csrf=False)
    @jwt_required
    def ielts_review(self, log_id, **kw):
        try:
            body = _get_json_body()
            action = body.get('action')
            examiner_notes = body.get('examiner_notes', '')

            if action not in ('approve', 'reject', 'revise'):
                return _error_response('action must be approve, reject, or revise', 400)

            Log = request.env['encoach.ai.ielts.generation.log'].sudo()
            log = Log.browse(log_id)
            if not log.exists():
                return _error_response('Log not found', 404)

            status_map = {
                'approve': 'approved',
                'reject': 'rejected',
                'revise': 'revision_needed',
            }

            log.write({
                'review_status': status_map[action],
                'examiner_id': request.env.user.id,
                'examiner_notes': examiner_notes,
                'reviewed_at': fields.Datetime.now(),
            })

            return _json_response({'status': status_map[action], 'log_id': log_id})
        except Exception as e:
            _logger.exception('ielts_review failed')
            return _error_response(str(e), 500)
