"""
Membership API Routes
======================

API endpoints for membership application system:
- NIP lookup in KRS/CEIDG registries
- Draft save/load
- Application submission
- Company data requests
"""

import logging
from datetime import datetime

from flask import jsonify, request
from flask_login import current_user, login_required

from database import (
    SessionLocal, MembershipApplication, CompanyDataRequest, Company
)
from . import bp

logger = logging.getLogger(__name__)


# ============================================================
# NIP LOOKUP (KRS/CEIDG)
# ============================================================

@bp.route('/membership/lookup-nip', methods=['POST'])
@login_required
def lookup_nip():
    """
    Lookup company data by NIP (and optionally KRS) in official registries.

    Workflow:
    1. If KRS provided - directly query KRS Open API
    2. If only NIP - query Biała Lista VAT to get KRS, then KRS Open API
    3. If no KRS found - try CEIDG (for JDG/sole proprietorship)

    Returns company info for auto-fill in application form.
    """
    data = request.get_json()
    if not data:
        return jsonify({'success': False, 'error': 'Brak danych'}), 400

    nip = data.get('nip', '').strip().replace('-', '').replace(' ', '')
    krs = data.get('krs', '').strip().replace('-', '').replace(' ', '') if data.get('krs') else None

    if not nip or len(nip) != 10:
        return jsonify({'success': False, 'error': 'NIP musi mieć 10 cyfr'}), 400

    if not nip.isdigit():
        return jsonify({'success': False, 'error': 'NIP może zawierać tylko cyfry'}), 400

    # Option 1: If KRS provided, use it directly
    if krs and len(krs) >= 7 and krs.isdigit():
        krs_result = _lookup_krs_by_number(krs)
        if krs_result:
            return jsonify({
                'success': True,
                'source': 'KRS',
                'data': krs_result
            })

    # Option 2: Try KRS via NIP (uses Biała Lista VAT → KRS Open API)
    krs_result = _lookup_krs(nip)
    if krs_result:
        return jsonify({
            'success': True,
            'source': 'KRS',
            'data': krs_result
        })

    # Option 3: Try CEIDG (for JDG - sole proprietorship)
    ceidg_result = _lookup_ceidg(nip)
    if ceidg_result:
        return jsonify({
            'success': True,
            'source': 'CEIDG',
            'data': ceidg_result
        })

    # Not found in any registry
    return jsonify({
        'success': True,
        'source': 'manual',
        'data': None,
        'message': 'Firma nie została znaleziona w KRS ani CEIDG. Wypełnij dane ręcznie.'
    })


def _lookup_krs_by_number(krs_number):
    """Lookup in KRS registry directly by KRS number."""
    try:
        from krs_api_service import get_company_from_krs
        krs_normalized = krs_number.zfill(10)
        result = get_company_from_krs(krs_normalized)
        if result:
            return _parse_krs_data(result.to_dict())
    except ImportError:
        logger.warning("KRS API service not available")
    except Exception as e:
        logger.error(f"KRS lookup error for KRS {krs_number}: {e}")
    return None


def _lookup_krs(nip):
    """Lookup in KRS registry by NIP (via Biała Lista VAT → KRS Open API)."""
    try:
        from krs_api_service import krs_api_service
        result = krs_api_service.search_by_nip(nip)
        if result:
            return _parse_krs_data(result)
    except ImportError:
        logger.warning("KRS API service not available")
    except Exception as e:
        logger.error(f"KRS lookup error for NIP {nip}: {e}")
    return None


def _parse_krs_data(result):
    """Parse KRS data into standardized format."""
    # Parse address components
    address = result.get('adres', {})
    if isinstance(address, str):
        address = {'full': address}

    # Handle kontakt_krs for email/website
    kontakt = result.get('kontakt_krs', {}) or {}

    return {
        'name': result.get('nazwa'),
        'krs': result.get('krs'),
        'regon': result.get('regon'),
        'address_postal_code': address.get('kod_pocztowy') or address.get('kodPocztowy', ''),
        'address_city': address.get('miejscowosc', ''),
        'address_street': address.get('ulica', ''),
        'address_number': address.get('nr_domu') or address.get('nrDomu', ''),
        'founded_date': result.get('daty', {}).get('rejestracji') if isinstance(result.get('daty'), dict) else result.get('data_rejestracji'),
        'business_type': _detect_business_type_from_krs(result),
        'email': kontakt.get('email') or result.get('email'),
        'website': kontakt.get('www') or result.get('strona_www'),
        'raw': result
    }


def _lookup_ceidg(nip):
    """Lookup in CEIDG registry."""
    try:
        from ceidg_api_service import fetch_ceidg_by_nip
        result = fetch_ceidg_by_nip(nip)
        if result:
            address = result.get('adresDzialalnosci', {})

            return {
                'name': result.get('firma'),
                'regon': result.get('regon'),
                'address_postal_code': address.get('kodPocztowy', ''),
                'address_city': address.get('miejscowosc', ''),
                'address_street': address.get('ulica', ''),
                'address_number': address.get('budynek', ''),
                'founded_date': result.get('dataRozpoczeciaDzialalnosci'),
                'business_type': 'jdg',
                'email': result.get('email'),
                'website': result.get('stronaWWW'),
                'raw': result
            }
    except ImportError:
        logger.warning("CEIDG API service not available")
    except Exception as e:
        logger.error(f"CEIDG lookup error for NIP {nip}: {e}")
    return None


def _detect_business_type_from_krs(data):
    """Detect business type from KRS data."""
    legal_form = data.get('forma_prawna', '').lower()

    if 'akcyjna' in legal_form and 'komandytowo' in legal_form:
        return 'spolka_komandytowo_akcyjna'
    elif 'akcyjna' in legal_form:
        return 'spolka_akcyjna'
    elif 'z ograniczoną odpowiedzialnością' in legal_form or 'z o.o.' in legal_form:
        if 'komandytowa' in legal_form:
            return 'sp_z_oo_komandytowa'
        return 'sp_z_oo'
    elif 'komandytowa' in legal_form:
        return 'spolka_komandytowa'
    elif 'partnerska' in legal_form:
        return 'spolka_partnerska'
    elif 'jawna' in legal_form:
        return 'spolka_jawna'
    elif 'cywilna' in legal_form:
        return 'spolka_cywilna'

    return 'inna'


# ============================================================
# MEMBERSHIP APPLICATION DRAFT
# ============================================================

@bp.route('/membership/draft', methods=['GET'])
@login_required
def get_draft():
    """Get current draft application."""
    db = SessionLocal()
    try:
        application = db.query(MembershipApplication).filter(
            MembershipApplication.user_id == current_user.id,
            MembershipApplication.status.in_(['draft', 'changes_requested'])
        ).first()

        if not application:
            return jsonify({'success': True, 'draft': None})

        return jsonify({
            'success': True,
            'draft': _serialize_application(application)
        })
    finally:
        db.close()


@bp.route('/membership/draft', methods=['POST'])
@login_required
def save_draft():
    """Save draft application data."""
    data = request.get_json()
    if not data:
        return jsonify({'success': False, 'error': 'Brak danych'}), 400

    db = SessionLocal()
    try:
        # Get or create draft
        application = db.query(MembershipApplication).filter(
            MembershipApplication.user_id == current_user.id,
            MembershipApplication.status.in_(['draft', 'changes_requested'])
        ).first()

        if not application:
            application = MembershipApplication(
                user_id=current_user.id,
                company_name=data.get('company_name', ''),
                nip=data.get('nip', ''),
                email=data.get('email', current_user.email or ''),
                status='draft'
            )
            db.add(application)

        # Update fields
        _update_application_from_data(application, data)
        application.updated_at = datetime.now()

        db.commit()

        return jsonify({
            'success': True,
            'message': 'Zapisano',
            'application_id': application.id
        })
    except Exception as e:
        db.rollback()
        logger.error(f"Error saving draft: {e}")
        return jsonify({'success': False, 'error': str(e)}), 500
    finally:
        db.close()


def _update_application_from_data(app, data):
    """Update application fields from request data."""
    # Step 1 fields
    if 'company_name' in data:
        app.company_name = data['company_name'].strip()
    if 'nip' in data:
        app.nip = data['nip'].strip().replace('-', '').replace(' ', '')
    if 'address_postal_code' in data:
        app.address_postal_code = data['address_postal_code'].strip()
    if 'address_city' in data:
        app.address_city = data['address_city'].strip()
    if 'address_street' in data:
        app.address_street = data['address_street'].strip()
    if 'address_number' in data:
        app.address_number = data['address_number'].strip()
    if 'delegate_1' in data:
        app.delegate_1 = data['delegate_1'].strip()
    if 'delegate_2' in data:
        app.delegate_2 = data['delegate_2'].strip()
    if 'delegate_3' in data:
        app.delegate_3 = data['delegate_3'].strip()
    if 'krs_number' in data:
        app.krs_number = data['krs_number'].strip()
    if 'regon' in data:
        app.regon = data['regon'].strip()
    if 'registry_source' in data:
        app.registry_source = data['registry_source']
    if 'registry_data' in data:
        app.registry_data = data['registry_data']

    # Step 2 fields
    if 'website' in data:
        app.website = data['website'].strip()
    if 'email' in data:
        app.email = data['email'].strip()
    if 'phone' in data:
        app.phone = data['phone'].strip()
    if 'short_name' in data:
        app.short_name = data['short_name'].strip()
    if 'description' in data:
        app.description = data['description'].strip()
    if 'founded_date' in data and data['founded_date']:
        try:
            app.founded_date = datetime.strptime(data['founded_date'], '%Y-%m-%d').date()
        except ValueError:
            pass
    if 'employee_count' in data and data['employee_count']:
        try:
            app.employee_count = int(data['employee_count'])
        except ValueError:
            pass
    if 'show_employee_count' in data:
        app.show_employee_count = bool(data['show_employee_count'])
    if 'annual_revenue' in data:
        app.annual_revenue = data['annual_revenue'].strip() if data['annual_revenue'] else None
    if 'related_companies' in data:
        app.related_companies = data['related_companies'] if data['related_companies'] else None

    # Step 3 fields
    if 'sections' in data:
        app.sections = data['sections'] if data['sections'] else []
    if 'sections_other' in data:
        app.sections_other = data['sections_other'].strip() if data['sections_other'] else None
    if 'business_type' in data:
        app.business_type = data['business_type']
    if 'business_type_other' in data:
        app.business_type_other = data['business_type_other'].strip() if data['business_type_other'] else None
    if 'consent_email' in data:
        app.consent_email = bool(data['consent_email'])
    if 'consent_email_address' in data:
        app.consent_email_address = data['consent_email_address'].strip() if data['consent_email_address'] else None
    if 'consent_sms' in data:
        app.consent_sms = bool(data['consent_sms'])
    if 'consent_sms_phone' in data:
        app.consent_sms_phone = data['consent_sms_phone'].strip() if data['consent_sms_phone'] else None


def _serialize_application(app):
    """Serialize application to dict."""
    return {
        'id': app.id,
        'status': app.status,
        'company_name': app.company_name,
        'nip': app.nip,
        'address_postal_code': app.address_postal_code,
        'address_city': app.address_city,
        'address_street': app.address_street,
        'address_number': app.address_number,
        'delegate_1': app.delegate_1,
        'delegate_2': app.delegate_2,
        'delegate_3': app.delegate_3,
        'krs_number': app.krs_number,
        'regon': app.regon,
        'registry_source': app.registry_source,
        'website': app.website,
        'email': app.email,
        'phone': app.phone,
        'short_name': app.short_name,
        'description': app.description,
        'founded_date': app.founded_date.isoformat() if app.founded_date else None,
        'employee_count': app.employee_count,
        'show_employee_count': app.show_employee_count,
        'annual_revenue': app.annual_revenue,
        'related_companies': app.related_companies,
        'sections': app.sections,
        'sections_other': app.sections_other,
        'business_type': app.business_type,
        'business_type_other': app.business_type_other,
        'consent_email': app.consent_email,
        'consent_email_address': app.consent_email_address,
        'consent_sms': app.consent_sms,
        'consent_sms_phone': app.consent_sms_phone,
        'declaration_accepted': app.declaration_accepted,
        'created_at': app.created_at.isoformat() if app.created_at else None,
        'updated_at': app.updated_at.isoformat() if app.updated_at else None,
        'submitted_at': app.submitted_at.isoformat() if app.submitted_at else None
    }


# ============================================================
# MEMBERSHIP APPLICATION SUBMIT
# ============================================================

@bp.route('/membership/submit', methods=['POST'])
@login_required
def submit_application():
    """Submit draft application for review."""
    db = SessionLocal()
    try:
        application = db.query(MembershipApplication).filter(
            MembershipApplication.user_id == current_user.id,
            MembershipApplication.status.in_(['draft', 'changes_requested'])
        ).first()

        if not application:
            return jsonify({'success': False, 'error': 'Nie znaleziono deklaracji'}), 404

        # Validate
        errors = _validate_application(application)
        if errors:
            return jsonify({'success': False, 'errors': errors}), 400

        # Submit
        application.status = 'submitted'
        application.submitted_at = datetime.now()
        application.declaration_accepted_at = datetime.now()
        application.declaration_ip_address = request.remote_addr
        db.commit()

        logger.info(f"Membership application submitted: user={current_user.id}, app={application.id}")

        return jsonify({
            'success': True,
            'message': 'Deklaracja została wysłana do rozpatrzenia',
            'application_id': application.id
        })
    except Exception as e:
        db.rollback()
        logger.error(f"Error submitting application: {e}")
        return jsonify({'success': False, 'error': str(e)}), 500
    finally:
        db.close()


def _validate_application(app):
    """Validate application before submission."""
    errors = []

    if not app.company_name:
        errors.append('Nazwa firmy jest wymagana')
    if not app.nip or len(app.nip) != 10:
        errors.append('NIP jest wymagany (10 cyfr)')
    if not app.email:
        errors.append('Email jest wymagany')
    if not app.delegate_1:
        errors.append('Przynajmniej jeden delegat jest wymagany')
    if not app.sections:
        errors.append('Wybierz przynajmniej jedną sekcję tematyczną')
    if not app.consent_email:
        errors.append('Zgoda na kontakt email jest wymagana')
    if not app.declaration_accepted:
        errors.append('Musisz zaakceptować oświadczenie')

    return errors


# ============================================================
# MEMBERSHIP STATUS
# ============================================================

@bp.route('/membership/status', methods=['GET'])
@login_required
def get_status():
    """Get application status for current user."""
    db = SessionLocal()
    try:
        applications = db.query(MembershipApplication).filter(
            MembershipApplication.user_id == current_user.id
        ).order_by(MembershipApplication.created_at.desc()).all()

        return jsonify({
            'success': True,
            'applications': [
                {
                    'id': app.id,
                    'status': app.status,
                    'status_label': app.status_label,
                    'company_name': app.company_name,
                    'created_at': app.created_at.isoformat() if app.created_at else None,
                    'submitted_at': app.submitted_at.isoformat() if app.submitted_at else None,
                    'reviewed_at': app.reviewed_at.isoformat() if app.reviewed_at else None,
                    'review_comment': app.review_comment
                }
                for app in applications
            ]
        })
    finally:
        db.close()


# ============================================================
# COMPANY DATA REQUEST
# ============================================================

@bp.route('/company/data-request', methods=['POST'])
@login_required
def create_data_request():
    """Create a company data update request."""
    data = request.get_json()
    if not data:
        return jsonify({'success': False, 'error': 'Brak danych'}), 400

    if not current_user.company_id:
        return jsonify({'success': False, 'error': 'Nie masz przypisanej firmy'}), 400

    nip = data.get('nip', '').strip().replace('-', '').replace(' ', '')
    if not nip or len(nip) != 10:
        return jsonify({'success': False, 'error': 'NIP musi mieć 10 cyfr'}), 400

    db = SessionLocal()
    try:
        # Check for existing pending request
        existing = db.query(CompanyDataRequest).filter(
            CompanyDataRequest.user_id == current_user.id,
            CompanyDataRequest.company_id == current_user.company_id,
            CompanyDataRequest.status == 'pending'
        ).first()

        if existing:
            return jsonify({'success': False, 'error': 'Masz już oczekujące zgłoszenie'}), 400

        # Fetch registry data
        registry_data = None
        registry_source = None

        krs_result = _lookup_krs(nip)
        if krs_result:
            registry_data = krs_result
            registry_source = 'KRS'
        else:
            ceidg_result = _lookup_ceidg(nip)
            if ceidg_result:
                registry_data = ceidg_result
                registry_source = 'CEIDG'

        # Create request
        data_request = CompanyDataRequest(
            request_type=data.get('request_type', 'update_data'),
            user_id=current_user.id,
            company_id=current_user.company_id,
            nip=nip,
            registry_source=registry_source,
            fetched_data=registry_data,
            user_note=data.get('user_note', '').strip() if data.get('user_note') else None
        )

        db.add(data_request)
        db.commit()

        logger.info(f"Company data request created: user={current_user.id}, company={current_user.company_id}")

        return jsonify({
            'success': True,
            'message': 'Zgłoszenie zostało wysłane do rozpatrzenia',
            'request_id': data_request.id,
            'registry_data': registry_data
        })
    except Exception as e:
        db.rollback()
        logger.error(f"Error creating data request: {e}")
        return jsonify({'success': False, 'error': str(e)}), 500
    finally:
        db.close()


@bp.route('/company/data-request/status', methods=['GET'])
@login_required
def get_data_request_status():
    """Get company data request status."""
    if not current_user.company_id:
        return jsonify({'success': True, 'requests': []})

    db = SessionLocal()
    try:
        requests = db.query(CompanyDataRequest).filter(
            CompanyDataRequest.user_id == current_user.id
        ).order_by(CompanyDataRequest.created_at.desc()).all()

        return jsonify({
            'success': True,
            'requests': [
                {
                    'id': req.id,
                    'request_type': req.request_type,
                    'request_type_label': req.request_type_label,
                    'status': req.status,
                    'status_label': req.status_label,
                    'nip': req.nip,
                    'registry_source': req.registry_source,
                    'created_at': req.created_at.isoformat() if req.created_at else None,
                    'reviewed_at': req.reviewed_at.isoformat() if req.reviewed_at else None,
                    'review_comment': req.review_comment
                }
                for req in requests
            ]
        })
    finally:
        db.close()
