"""DPIA skeleton generator.

Reads the audit log and generates a Data Protection Impact Assessment
skeleton in Markdown. Covers ~60% of a DPIA automatically — data flows,
PII types, providers, purposes, and risk identification.

The output is a working document, not a finished DPIA. It needs human
review, legal assessment, and sign-off. But it saves hours of manual work.
"""

import time
from datetime import datetime, timezone
from typing import Optional

from .audit import AuditLog


def generate(
    audit_log: AuditLog,
    system_name: str = "AI Agent System",
    controller_name: str = "",
    dpo_contact: str = "",
) -> str:
    """Generate a DPIA skeleton from audit log data.

    Args:
        audit_log: The audit log to analyse.
        system_name: Name of the AI system being assessed.
        controller_name: Name of the data controller organisation.
        dpo_contact: DPO contact details.

    Returns:
        Markdown string containing the DPIA skeleton.
    """
    stats = audit_log.stats()
    entries = audit_log.query()

    if not entries:
        return _empty_dpia(system_name, controller_name, dpo_contact)

    # Analyse data flows
    providers = stats.get("providers", {})
    purposes = stats.get("purposes", {})
    pii_types = stats.get("pii_detected", {})
    total_entries = stats.get("total_entries", 0)

    # Find unique users
    user_ids = set()
    for e in entries:
        uid = e.get("user_id")
        if uid:
            user_ids.add(uid)

    # Time range
    timestamps = [e.get("timestamp", 0) for e in entries]
    earliest = datetime.fromtimestamp(min(timestamps), tz=timezone.utc) if timestamps else None
    latest = datetime.fromtimestamp(max(timestamps), tz=timezone.utc) if timestamps else None

    now = datetime.now(timezone.utc).strftime("%Y-%m-%d")

    sections = []

    # Header
    sections.append(f"""# Data Protection Impact Assessment
## {system_name}

| Field | Value |
|-------|-------|
| Date | {now} |
| Data Controller | {controller_name or '[YOUR ORGANISATION]'} |
| DPO Contact | {dpo_contact or '[DPO EMAIL/PHONE]'} |
| System Name | {system_name} |
| Assessment Status | DRAFT — requires review |

---

> **Note:** This DPIA skeleton was auto-generated by [agent-shield](https://github.com/Thezenmonster/agent-shield)
> from audit log data. It requires human review, legal assessment, and sign-off
> before it constitutes a valid DPIA.
>
> For professional DPIA services, contact [Janus Compliance](https://januscompliance.co.uk/contact).
""")

    # Section 1: Description of processing
    sections.append(f"""## 1. Description of Processing

### 1.1 Nature of Processing

This system makes calls to external AI/LLM providers to process user inputs
and generate responses. Based on audit log analysis:

- **Total processing events recorded:** {total_entries}
- **Unique users processed:** {len(user_ids)}
- **Assessment period:** {earliest.strftime('%Y-%m-%d') if earliest else 'N/A'} to {latest.strftime('%Y-%m-%d') if latest else 'N/A'}

### 1.2 Purposes of Processing

{_format_purposes(purposes)}

### 1.3 Categories of Personal Data Processed

{_format_pii_types(pii_types)}

### 1.4 Data Recipients (External Providers)

{_format_providers(providers)}
""")

    # Section 2: Necessity and proportionality
    sections.append("""## 2. Necessity and Proportionality

### 2.1 Lawful Basis

- [ ] Consent (Article 6(1)(a) GDPR / NDPA equivalent)
- [ ] Contract performance (Article 6(1)(b))
- [ ] Legal obligation (Article 6(1)(c))
- [ ] Legitimate interest (Article 6(1)(f))

**[ASSESSOR: Select the applicable lawful basis and document the justification.]**

### 2.2 Data Minimisation

**[ASSESSOR: Review whether the personal data sent to LLM providers is the
minimum necessary for the processing purpose. Consider whether PII redaction
should be enabled (agent-shield supports automatic redaction).]**

### 2.3 Retention

**[ASSESSOR: Document how long audit logs, conversation data, and processed
outputs are retained. Set retention periods and deletion schedules.]**
""")

    # Section 3: Risks
    risks = _identify_risks(providers, pii_types, len(user_ids))
    sections.append(f"""## 3. Risk Assessment

{risks}
""")

    # Section 4: Mitigations
    sections.append(f"""## 4. Mitigations

### 4.1 Technical Measures Currently in Place

- [x] **PII detection** — automatic scanning of all inputs (agent-shield)
- [{'x' if any(e.get('metadata', {}).get('redacted') for e in entries) else ' '}] **PII redaction** — automatic redaction before sending to providers
- [x] **Audit logging** — tamper-evident log of all processing events
- [x] **Chain integrity** — hash-chain verification of audit trail
- [{'x' if user_ids else ' '}] **User tracking** — per-user processing records for data subject requests

### 4.2 Additional Measures Required

- [ ] Data Processing Agreements with all LLM providers
- [ ] Privacy notices updated to reflect AI processing
- [ ] Consent mechanism implemented (if consent is the lawful basis)
- [ ] Data retention policy defined and enforced
- [ ] Access controls on audit logs and processed data
- [ ] Incident response plan covering AI-related breaches
- [ ] Regular review schedule established

### 4.3 Recommended Actions

{_recommend_actions(providers, pii_types, entries)}
""")

    # Section 5: Sign-off
    sections.append("""## 5. Decision

**[ASSESSOR: Based on the risks identified and mitigations in place, document
the decision to proceed, proceed with conditions, or not proceed.]**

| Role | Name | Date | Signature |
|------|------|------|-----------|
| DPO / Privacy Lead | | | |
| System Owner | | | |
| Senior Management | | | |

---

*Generated by [agent-shield](https://github.com/Thezenmonster/agent-shield) v0.1.0.
For professional DPIA review and completion, contact
[Janus Compliance](https://januscompliance.co.uk/contact) — CIPP/E certified,
specialising in AI compliance.*
""")

    return "\n".join(sections)


def _format_purposes(purposes: dict) -> str:
    if not purposes:
        return "No processing purposes recorded in audit log.\n\n**[ASSESSOR: Document all purposes.]**"
    lines = []
    for purpose, count in sorted(purposes.items(), key=lambda x: -x[1]):
        lines.append(f"| {purpose} | {count} events |")
    return "| Purpose | Volume |\n|---------|--------|\n" + "\n".join(lines)


def _format_pii_types(pii_types: dict) -> str:
    if not pii_types:
        return "No PII detected in recorded inputs.\n\n**Note:** This may indicate PII redaction is working correctly, or that inputs don't contain detectable PII patterns."
    lines = []
    for pii_type, count in sorted(pii_types.items(), key=lambda x: -x[1]):
        lines.append(f"| {pii_type} | {count} instances |")
    return "| PII Type | Instances Detected |\n|----------|-------------------|\n" + "\n".join(lines)


def _format_providers(providers: dict) -> str:
    if not providers:
        return "No external providers recorded."

    provider_info = {
        "openai": ("OpenAI", "United States", "High — processes input text"),
        "anthropic": ("Anthropic", "United States", "High — processes input text"),
        "google": ("Google", "United States / EU", "High — processes input text"),
        "custom": ("Custom / Self-hosted", "Unknown", "Varies"),
    }

    lines = []
    for provider, count in sorted(providers.items(), key=lambda x: -x[1]):
        name, country, risk = provider_info.get(
            provider, (provider, "Unknown", "Unknown")
        )
        lines.append(f"| {name} | {country} | {count} calls | {risk} |")

    return "| Provider | Country | Volume | Data Exposure |\n|----------|---------|--------|---------------|\n" + "\n".join(lines)


def _identify_risks(providers: dict, pii_types: dict, user_count: int) -> str:
    risks = []
    risk_num = 1

    if pii_types:
        pii_list = ", ".join(pii_types.keys())
        risks.append(
            f"| {risk_num} | PII sent to external providers | High | "
            f"Personal data ({pii_list}) is being sent to external LLM providers. "
            f"If providers retain or use this data, it constitutes further processing. |"
        )
        risk_num += 1

    for provider in providers:
        if provider in ("openai", "anthropic", "google"):
            risks.append(
                f"| {risk_num} | Cross-border data transfer ({provider}) | High | "
                f"Data is transferred to {provider} servers, likely outside Nigeria/EU. "
                f"Transfer mechanisms and DPA required. |"
            )
            risk_num += 1

    if user_count > 100:
        risks.append(
            f"| {risk_num} | Large-scale processing | Medium | "
            f"{user_count} unique users processed. Scale increases impact of any breach. |"
        )
        risk_num += 1

    if not pii_types:
        risks.append(
            f"| {risk_num} | Undetected PII | Medium | "
            f"No PII detected by automated scanning. Manual review recommended — "
            f"regex patterns may miss context-dependent PII (names, addresses). |"
        )
        risk_num += 1

    risks.append(
        f"| {risk_num} | Model output containing PII | Medium | "
        f"LLM responses may generate or reveal personal data not present in the input. "
        f"Output monitoring recommended. |"
    )

    if not risks:
        return "No automated risks identified. Manual assessment required."

    header = "| # | Risk | Severity | Description |\n|---|------|----------|-------------|\n"
    return header + "\n".join(risks)


def _recommend_actions(providers: dict, pii_types: dict, entries: list) -> str:
    actions = []

    has_redaction = any(e.get("metadata", {}).get("redacted") for e in entries)
    if pii_types and not has_redaction:
        actions.append(
            "1. **Enable PII redaction.** PII is being detected but not redacted before "
            "sending to providers. Set `redact_input=True` in your Shield configuration."
        )

    for provider in providers:
        if provider in ("openai", "anthropic", "google"):
            actions.append(
                f"1. **Sign DPA with {provider}.** Ensure a Data Processing Agreement "
                f"is in place covering data handling, retention, and sub-processors."
            )

    actions.append(
        "1. **Set data retention periods.** Define how long audit logs and processed "
        "data are retained. Implement automated deletion."
    )
    actions.append(
        "1. **Update privacy notices.** Inform users that their data is processed "
        "by AI systems and transferred to external providers."
    )

    return "\n".join(actions) if actions else "No automated recommendations. Manual review required."


def _empty_dpia(system_name: str, controller_name: str, dpo_contact: str) -> str:
    now = datetime.now(timezone.utc).strftime("%Y-%m-%d")
    return f"""# Data Protection Impact Assessment
## {system_name}

| Field | Value |
|-------|-------|
| Date | {now} |
| Data Controller | {controller_name or '[YOUR ORGANISATION]'} |
| DPO Contact | {dpo_contact or '[DPO EMAIL/PHONE]'} |
| Assessment Status | DRAFT — no audit data available |

No audit log data found. Run your AI agent with agent-shield enabled to
collect processing data, then regenerate this DPIA.

*Generated by [agent-shield](https://github.com/Thezenmonster/agent-shield).
For professional DPIA services, contact [Janus Compliance](https://januscompliance.co.uk/contact).*
"""
