from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify
from flask_login import login_required, current_user
from app import db
from app.models import PurchaseRequest, PurchaseRequestItem, PurchaseOrder, PurchaseOrderItem, Vendor, Project, ProjectCost
from datetime import datetime
from decimal import Decimal

procurement_bp = Blueprint('procurement', __name__)

def generate_pr_number():
    year = datetime.now().year
    month = datetime.now().month
    count = PurchaseRequest.query.filter(PurchaseRequest.pr_number.like(f'PR-{year}{month:02d}-%')).count() + 1
    return f'PR-{year}{month:02d}-{count:04d}'

def generate_po_number():
    year = datetime.now().year
    month = datetime.now().month
    count = PurchaseOrder.query.filter(PurchaseOrder.po_number.like(f'PO-{year}{month:02d}-%')).count() + 1
    return f'PO-{year}{month:02d}-{count:04d}'

# ─── Purchase Request ──────────────────────────────────────────────────────────

@procurement_bp.route('/pr')
@login_required
def pr_list():
    status = request.args.get('status', 'all')
    query = PurchaseRequest.query
    if status != 'all':
        query = query.filter_by(status=status)
    prs = query.order_by(PurchaseRequest.created_at.desc()).all()
    return render_template('procurement/pr_list.html', prs=prs, current_status=status)

@procurement_bp.route('/pr/create', methods=['GET', 'POST'])
@login_required
def pr_create():
    if request.method == 'POST':
        pr = PurchaseRequest(
            pr_number=generate_pr_number(),
            project_id=int(request.form['project_id']),
            request_date=datetime.strptime(request.form['request_date'], '%Y-%m-%d').date(),
            needed_date=datetime.strptime(request.form['needed_date'], '%Y-%m-%d').date() if request.form.get('needed_date') else None,
            priority=request.form.get('priority', 'normal'),
            notes=request.form.get('notes'),
            requested_by=current_user.id
        )
        db.session.add(pr)
        db.session.flush()

        total = Decimal('0')
        item_names = request.form.getlist('item_name[]')
        for i, item_name in enumerate(item_names):
            if not item_name.strip():
                continue
            qty = Decimal(request.form.getlist('quantity[]')[i])
            price = Decimal(request.form.getlist('estimated_price[]')[i].replace(',', '') or '0')
            item = PurchaseRequestItem(
                pr_id=pr.id,
                item_name=item_name,
                specification=request.form.getlist('specification[]')[i] if request.form.getlist('specification[]') else '',
                quantity=qty,
                unit=request.form.getlist('unit[]')[i],
                estimated_price=price,
                cost_category=request.form.getlist('cost_category[]')[i] if request.form.getlist('cost_category[]') else '',
            )
            db.session.add(item)
            total += qty * price

        pr.total_amount = total
        db.session.commit()
        flash(f'Purchase Request {pr.pr_number} berhasil dibuat!', 'success')
        return redirect(url_for('procurement.pr_detail', id=pr.id))

    projects = Project.query.filter_by(status='active').all()
    return render_template('procurement/pr_create.html', projects=projects)

@procurement_bp.route('/pr/<int:id>')
@login_required
def pr_detail(id):
    pr = PurchaseRequest.query.get_or_404(id)
    items = PurchaseRequestItem.query.filter_by(pr_id=id).all()
    return render_template('procurement/pr_detail.html', pr=pr, items=items)

@procurement_bp.route('/pr/<int:id>/submit', methods=['POST'])
@login_required
def pr_submit(id):
    pr = PurchaseRequest.query.get_or_404(id)
    if pr.status == 'draft':
        pr.status = 'submitted'
        db.session.commit()
        flash(f'PR {pr.pr_number} berhasil diajukan untuk persetujuan!', 'success')
    return redirect(url_for('procurement.pr_detail', id=id))

@procurement_bp.route('/pr/<int:id>/approve', methods=['POST'])
@login_required
def pr_approve(id):
    pr = PurchaseRequest.query.get_or_404(id)
    action = request.form.get('action')
    if action == 'approve':
        pr.status = 'approved'
        pr.approved_by = current_user.id
        pr.approved_at = datetime.utcnow()
        flash(f'PR {pr.pr_number} berhasil disetujui!', 'success')
    else:
        pr.status = 'rejected'
        flash(f'PR {pr.pr_number} ditolak.', 'warning')
    db.session.commit()
    return redirect(url_for('procurement.pr_detail', id=id))

# ─── Purchase Order ────────────────────────────────────────────────────────────

@procurement_bp.route('/po')
@login_required
def po_list():
    status = request.args.get('status', 'all')
    query = PurchaseOrder.query
    if status != 'all':
        query = query.filter_by(status=status)
    pos = query.order_by(PurchaseOrder.created_at.desc()).all()
    return render_template('procurement/po_list.html', pos=pos, current_status=status)

@procurement_bp.route('/po/create', methods=['GET', 'POST'])
@procurement_bp.route('/po/create/<int:pr_id>', methods=['GET', 'POST'])
@login_required
def po_create(pr_id=None):
    pr = PurchaseRequest.query.get(pr_id) if pr_id else None
    if request.method == 'POST':
        subtotal = Decimal('0')
        po = PurchaseOrder(
            po_number=generate_po_number(),
            pr_id=int(request.form['pr_id']) if request.form.get('pr_id') else None,
            project_id=int(request.form['project_id']),
            vendor_id=int(request.form['vendor_id']),
            order_date=datetime.strptime(request.form['order_date'], '%Y-%m-%d').date(),
            delivery_date=datetime.strptime(request.form['delivery_date'], '%Y-%m-%d').date() if request.form.get('delivery_date') else None,
            payment_terms=request.form.get('payment_terms'),
            notes=request.form.get('notes'),
            created_by=current_user.id
        )
        db.session.add(po)
        db.session.flush()

        item_names = request.form.getlist('item_name[]')
        for i, item_name in enumerate(item_names):
            if not item_name.strip():
                continue
            qty = Decimal(request.form.getlist('quantity[]')[i])
            price = Decimal(request.form.getlist('unit_price[]')[i].replace(',', '') or '0')
            tax = Decimal(request.form.getlist('tax_rate[]')[i] or '11')
            total = qty * price * (1 + tax / 100)
            item = PurchaseOrderItem(
                po_id=po.id,
                item_name=item_name,
                specification=request.form.getlist('specification[]')[i] if request.form.getlist('specification[]') else '',
                quantity=qty,
                unit=request.form.getlist('unit[]')[i],
                unit_price=price,
                tax_rate=tax,
                total_price=total
            )
            db.session.add(item)
            subtotal += qty * price

        tax_total = subtotal * Decimal('0.11')
        po.subtotal = subtotal
        po.tax_amount = tax_total
        po.total_amount = subtotal + tax_total

        if pr:
            pr.status = 'ordered'

        db.session.commit()
        flash(f'Purchase Order {po.po_number} berhasil dibuat!', 'success')
        return redirect(url_for('procurement.po_detail', id=po.id))

    projects = Project.query.filter_by(status='active').all()
    vendors = Vendor.query.filter_by(is_active=True).all()
    approved_prs = PurchaseRequest.query.filter_by(status='approved').all()
    return render_template('procurement/po_create.html', projects=projects, vendors=vendors, pr=pr, approved_prs=approved_prs)

@procurement_bp.route('/po/<int:id>')
@login_required
def po_detail(id):
    po = PurchaseOrder.query.get_or_404(id)
    items = PurchaseOrderItem.query.filter_by(po_id=id).all()
    return render_template('procurement/po_detail.html', po=po, items=items)

@procurement_bp.route('/po/<int:id>/receive', methods=['POST'])
@login_required
def po_receive(id):
    po = PurchaseOrder.query.get_or_404(id)
    po.status = 'received'
    # Auto-record project cost
    cost = ProjectCost(
        project_id=po.project_id,
        cost_category='Pengadaan Barang/Jasa',
        description=f'Penerimaan PO {po.po_number} dari {po.vendor.vendor_name}',
        amount=po.total_amount,
        transaction_date=datetime.today().date(),
        reference_number=po.po_number,
        vendor_name=po.vendor.vendor_name,
        purchase_order_id=po.id,
        created_by=current_user.id
    )
    db.session.add(cost)
    db.session.commit()
    flash(f'PO {po.po_number} diterima dan biaya proyek dicatat otomatis!', 'success')
    return redirect(url_for('procurement.po_detail', id=id))

# ─── Vendor ────────────────────────────────────────────────────────────────────

@procurement_bp.route('/vendors')
@login_required
def vendor_list():
    vendors = Vendor.query.order_by(Vendor.vendor_name).all()
    return render_template('procurement/vendor_list.html', vendors=vendors)

@procurement_bp.route('/vendors/create', methods=['GET', 'POST'])
@login_required
def vendor_create():
    if request.method == 'POST':
        # Generate vendor code based on max ID to avoid duplicates after deletions
        max_id = db.session.query(db.func.max(Vendor.id)).scalar() or 0
        count = max_id + 1
        vendor = Vendor(
            vendor_code=f'VND-{count:04d}',
            vendor_name=request.form['vendor_name'],
            npwp=request.form.get('npwp'),
            address=request.form.get('address'),
            phone=request.form.get('phone'),
            email=request.form.get('email'),
            contact_person=request.form.get('contact_person'),
            bank_name=request.form.get('bank_name'),
            bank_account=request.form.get('bank_account')
        )
        db.session.add(vendor)
        db.session.commit()
        flash(f'Vendor {vendor.vendor_name} berhasil ditambahkan!', 'success')
        return redirect(url_for('procurement.vendor_list'))
    return render_template('procurement/vendor_create.html')
