from decimal import Decimal
from django.forms import ValidationError, formset_factory
from django.shortcuts import render, redirect, get_object_or_404
from django.core.paginator import Paginator
from django.db.models import Sum, Q, Count
import datetime
from django.utils import timezone
from .forms import ProjectDocumentForm, ProjectForm
from accounting.models import PurchaseOrder, Transaction, JournalEntry, Account
from django.db.models import Count
from django.template.loader import render_to_string
from django.http import JsonResponse
from .models import Project, ProjectDocument
# from pdf_processor import extract_goods_declaration
import os
from django.conf import settings

# Create your views here.
# Project List View with Search & Pagination
def project_list(request):
    query = request.GET.get("q")
    projects = Project.objects.all()
    if query:
        projects = projects.filter(Q(project_description__icontains=query))
        
    paginator = Paginator(projects, 10)
    page_number = request.GET.get("page")
    page_obj = paginator.get_page(page_number)

    return render(request, "projects/project_list.html", {"page_obj": page_obj, "query": query})

# ✅ Add, Edit, Delete Project
def add_project(request):
    if request.method == "POST":
        form = ProjectForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect("project_list")
        else:
            print(form.errors)
    else:
        form = ProjectForm()
    return render(request, "projects/add_project.html", {"form": form})

def edit_project(request, pk):
    project = get_object_or_404(Project, pk=pk)
    if request.method == "POST":
        form = ProjectForm(request.POST, instance=project)
        if form.is_valid():
            form.save()
            return redirect("project_list")       
    else:
        form = ProjectForm(instance=project)
    return render(request, "projects/edit_project.html", {"form": form, "project": project})

def delete_project(request, pk):
    project = get_object_or_404(Project, pk=pk)
    if request.method == "POST":
        project.delete()
        return redirect("project_list")
    return render(request, "projects/delete_project.html", {"project": project})

def project_dashboard(request, project_id):
    project = get_object_or_404(Project, pk=project_id)

    # containers = ContainerDetail.objects.filter(bl_section=bl_section) if bl_section else []
    containers = []
   
    return render(request, 'projects/project_dashboard.html', {
        'project': project,
       
    })


def project_summary(request, project_id):
    project = get_object_or_404(Project, pk=project_id)

    # Include child projects
    project_ids = [project.id] 

    # Financials
    total_purchases = PurchaseOrder.objects.filter(project__in=project_ids, status='completed').aggregate(
        total=Sum('items__price'))['total'] or 0

    
    # Use account categories
    expense_accounts = Account.objects.filter(sub_type__category__name='Expense')
    revenue_accounts = Account.objects.filter(sub_type__category__name='Revenue')

    total_expenses = Transaction.objects.filter(
        journal_entry__project_id__in=project_ids,
        account__in=expense_accounts
    ).aggregate(amount=Sum('debit') - Sum('credit'))['amount'] or 0

    total_revenue = Transaction.objects.filter(
        journal_entry__project__in=project_ids,
        account__in=revenue_accounts
    ).aggregate(amount=Sum('credit') - Sum('debit'))['amount'] or 0

    # # Stock summary
    # total_stock_in = StockMovement.objects.filter(project__in=project_ids, movement_type='IN').aggregate(
    #     total=Sum('quantity'))['total'] or 0
    # total_stock_out = StockMovement.objects.filter(project__in=project_ids, movement_type='OUT').aggregate(
    #     total=Sum('quantity'))['total'] or 0

    context = {
        'project': project,
        'total_purchases': total_purchases,
        'total_sales': "",
        'total_expenses': total_expenses,
        'total_revenue': total_revenue,
        'net_profit': total_revenue - total_expenses,
        # 'stock_in': total_stock_in,
        # 'stock_out': total_stock_out,
        # 'current_stock': total_stock_in - total_stock_out,
    }

    return render(request, 'projects/project_summary.html', context)


def project_ledger(request, project_id):
    project = get_object_or_404(Project, pk=project_id)

    # Include child projects if this is a parent Project
    project_ids = [project.id]
    
    journal_entries = JournalEntry.objects.filter(project__in=project_ids).prefetch_related('transactions').order_by('date')

    ledger_data = []
    running_balance = 0

    for entry in journal_entries:
        for txn in entry.transactions.all():
            amount = txn.debit - txn.credit
            running_balance += amount

            ledger_data.append({
                'date': entry.date,
                'entry_number': entry.entry_number,
                'account': txn.account.name,
                'debit': txn.debit,
                'credit': txn.credit,
                'balance': running_balance,
                'description': txn.description,
            })

    context = {
        'project': project,
        'ledger_data': ledger_data,
    }
    return render(request, 'projects/project_ledger.html', context)


def project_income_statement(request, project_id):
    project = get_object_or_404(Project, pk=project_id)

    # Get all Project IDs including children
    project_ids = [project.id]
    
    # Get journal entries linked to this Project or sub-projects
    entries = JournalEntry.objects.filter(project__in=project_ids, status='posted')

    # Filter transactions from those entries
    transactions = Transaction.objects.filter(journal_entry__in=entries).select_related('account__sub_type__category')

    revenue = []
    expenses = []
    total_revenue = 0
    total_expense = 0

    for txn in transactions:
        account = txn.account
        amount = (txn.credit or 0) - (txn.debit or 0)

        if account.sub_type.category.name == 'Revenue':
            revenue.append({'account': account.name, 'amount': amount})
            total_revenue += amount
        elif account.sub_type.category.name == 'Expense':
            expenses.append({'account': account.name, 'amount': abs(amount)})
            total_expense += abs(amount)

    net_income = total_revenue - total_expense

    context = {
        
        'project': project,
        'revenues': revenue,
        'expenses': expenses,
        'total_revenue': total_revenue,
        'total_expense': total_expense,
        'net_income': net_income,
        'net_income_class': 'text-success' if net_income >= 0 else 'text-danger',
    }

    return render(request, 'projects/project_income_statement.html', context)


def project_purchases(request, project_id):
    project = get_object_or_404(Project, pk=project_id)

    # Include child projects if this is a parent Project
    project_ids = [project.id]
    
    # Fetch purchase orders with prefetch for items
    purchase_orders = (
        PurchaseOrder.objects
        .filter(project_id__in=project_ids)
        .select_related('supplier')
        .prefetch_related('items')
    )

    # Add total_amount attribute dynamically
    for po in purchase_orders:
        po.total_amount = sum(item.total_amount() for item in po.items.all())

   
   
    return render(request, 'projects/project_purchases.html', {
        'project': project,
        'purchase_orders': purchase_orders,
        
    })


# def Project document

def project_document_upload(request, project_id):
    project = get_object_or_404(Project, pk=project_id)

    if request.method == 'POST':
        form = ProjectDocumentForm(request.POST, request.FILES)
        if form.is_valid():
            document = form.save(commit=False)
            document.project = project  # Set the Project here from URL
            document.save()
            return redirect('project_document_upload', project_id=project.id)  # Redirect to the same Project
    else:
        form = ProjectDocumentForm()

    # documents = projectDocument.objects.filter(Project=Project).order_by('-uploaded_at')
    document_type_filter = request.GET.get('document_type')

    documents = ProjectDocument.objects.filter(project=project)

    if document_type_filter:
        documents = documents.filter(document_type=document_type_filter)
        
    return render(request, 'projects/project_document_upload.html', {
        'form': form,
        'project': project,
        'documents': documents
    })

def delete_project_document(request, document_id):
    doc = get_object_or_404(ProjectDocumentForm, id=document_id)
    project_id = doc.Project.id

    if request.method == 'POST':
        doc.delete()
        return redirect('project_document_upload', project_id=project_id)
    


   