from typing import assert_never


from vet.models.audits import AuditStatus
from vet.models.common import StrictStruct

START_BOLD = "\033[1m"
END_BOLD = "\033[0m"


def get_audit_description(audit_status: AuditStatus) -> str:
    if audit_status == AuditStatus.UNSAFE:
        return """"
This package is not safe to run or deploy.
It is suspected to contain serious security vulnerabilities or other issues which
could cause harm to users, systems, or data.
"""
    elif audit_status == AuditStatus.SAFE_TO_RUN:
        return """
This package can be compiled, run, and tested on a local workstation or in
controlled automation without surprising consequences, such as:
* Reading or writing data from sensitive or unrelated parts of the filesystem.
* Installing software or reconfiguring the device.
* Connecting to untrusted network endpoints.
* Misuse of system resources (e.g. cryptocurrency mining).
"""
    elif audit_status == AuditStatus.SAFE_TO_DEPLOY:
        return """
This package will not introduce a serious security vulnerability to production
software exposed to untrusted input.

Auditors are not required to perform a full logic review of the entire crate.
Rather, they must review enough to fully reason about the behavior of all unsafe
blocks and usage of powerful imports. For any reasonable usage of the crate in
real-world software, an attacker must not be able to manipulate the runtime
behavior of these sections in an exploitable or surprising way.

Ideally, all unsafe code is fully sound, and ambient capabilities (e.g.
filesystem access) are hardened against manipulation and consistent with the
advertised behavior of the crate. However, some discretion is permitted. In such
cases, the nature of the discretion should be recorded in the `notes` field of
the audit record.

For packages which generate deployed code (e.g. build dependencies or procedural
macros), reasonable usage of the crate should output code which meets the above
criteria.
"""
    else:
        assert_never(audit_status)


class StartInspectText(StrictStruct):
    package_name: str
    version: str
    likely_resulting_audit_status: AuditStatus
    url: None | str = None

    @property
    def text(self):
        result = f"""You are about to inspect version {self.version} of '{self.package_name}', 
likely to certify it as '{self.likely_resulting_audit_status}', which means:
"""
        result += get_audit_description(self.likely_resulting_audit_status)

        result += f"""{START_BOLD}
Please read the above criteria and consider them when performing the audit.
Other software packages may rely on this audit. Ask for help if you're not sure.
{END_BOLD}"""

        if self.url:
            result += f"""
You can inspect the crate here: {self.url}"""

        return result


class ExampleAudit(StrictStruct):
    commented: bool = False

    @property
    def text(self):
        example = '''[audits.example_package]
who = "Example Person <person@example.com>"
status = "safe to deploy"  # or "safe to run" or "unsafe"
version = "1.7.2"
notes = "Some notes about the audit"'''
        if self.commented:
            example = "\n".join(f"# {line}" for line in example.split("\n"))
        return example


class ReadmeText(StrictStruct):
    audit_file: str
    config_file: str
    import_lock_file: str

    @property
    def text(self):
        return f"""# Chain of Trust

## Audit file (`{self.audit_file}`)

Holds the audit records for packages in this project. 
Each record contains:
- `who` performed the audit,
- `status` of the audit (unsafe, safe to run, safe to deploy),
- `version` of the package that was audited.
- `notes` (optionally) about the audit.

Example:
```toml
{ExampleAudit().text}
```

## Config file (`{self.config_file}`)

### Exemptions

A list of packages that are exempt from audits. 
For sake of ease of getting started, all packages in the `poetry.lock` file are exempt by default.
These packages should be audited either manually or via import of an audit from a trusted source.

Example:
```toml
[exemptions.example_package]
version = "1.7.2"
status = "safe to deploy"
```

### Imports

A list of URLs to audit sources. 
Each source must provide a TOML file with audits (same as `{self.audit_file}`).

Example:
```toml
[imports.example_org]
url = "https://raw.githubusercontent.com/example_org/example_project/main/chain-of-trust/audits.toml"
```

## Import lock (`{self.import_lock_file}`)

This file is automatically generated by `vet`. 
Do not edit it manually.

It holds a local copy of audits from trusted sources specified in the config file.
"""


class ExemptionMatch(StrictStruct):
    package_name: str

    @property
    def text(self):
        return f"👍 {START_BOLD}{self.package_name}{END_BOLD} matches exemption"


class AuditMatch(StrictStruct):
    package_name: str
    is_exempt: bool

    @property
    def text(self):
        result = f"✅ {START_BOLD}{self.package_name}{END_BOLD} passes our audit"
        if self.is_exempt:
            result += "\n   (this package also matches an exemption; you should remove the exemption if it's no longer needed)"
        return result


class ImportedAuditMatch(StrictStruct):
    package_name: str
    org_name: str

    @property
    def text(self):
        return f"✅ {START_BOLD}{self.package_name}{END_BOLD} passes audit by {START_BOLD}{self.org_name}{END_BOLD}"


class FailedAuditMatch(StrictStruct):
    package_name: str

    @property
    def text(self):
        return f"❌ {START_BOLD}{self.package_name}{END_BOLD} fails audit"
