import json
import subprocess
import tempfile
import unittest
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
INSTALL = ROOT / 'scripts' / 'install_into_repo.sh'


class ArnesCoreTests(unittest.TestCase):
    def run_cmd(self, args, cwd=None, input_text=None, check=True):
        result = subprocess.run(
            args,
            cwd=cwd or ROOT,
            input=input_text,
            text=True,
            capture_output=True,
        )
        if check and result.returncode != 0:
            raise AssertionError(
                f"Command failed: {args}\nSTDOUT:\n{result.stdout}\nSTDERR:\n{result.stderr}"
            )
        return result

    def test_install_refuses_source_repo(self):
        result = self.run_cmd([str(INSTALL), str(ROOT)], check=False)
        self.assertNotEqual(result.returncode, 0)
        self.assertIn('Refusing to install ARNES into its own source repository', result.stdout)

    def test_install_start_verify_and_publish_in_external_repo(self):
        with tempfile.TemporaryDirectory() as tmp:
            tmp_path = Path(tmp)
            target = tmp_path / 'project-repo'
            remote = tmp_path / 'remote.git'

            self.run_cmd([str(INSTALL), str(target)])
            self.assertTrue((target / 'scripts' / 'start.sh').is_file())
            self.assertFalse((target / 'tests').exists(), 'source self-tests must not be installed into project repo')

            self.run_cmd(['git', 'config', 'user.name', 'ARNES Bot'], cwd=target)
            self.run_cmd(['git', 'config', 'user.email', 'arnes@example.com'], cwd=target)
            self.run_cmd(['git', 'init', '--bare', str(remote)])
            self.run_cmd(['git', 'remote', 'add', 'origin', str(remote)], cwd=target)

            wizard_input = '\n'.join([
                'demo-project',
                'Demo project',
                'project',
                '1',
                '',
                '',
                '',
                '',
            ]) + '\n'
            self.run_cmd(['./scripts/start.sh'], cwd=target, input_text=wizard_input)

            self.assertTrue((target / 'project' / 'tests').is_dir())
            cfg = json.loads((target / 'harness' / 'project.config.json').read_text(encoding='utf-8'))
            self.assertEqual(cfg['app_dir'], 'project')
            self.assertEqual(cfg['commands']['test'], 'python3 -m unittest discover -s project/tests -v')

            verify_result = self.run_cmd(['./scripts/verify.sh'], cwd=target)
            self.assertIn('Harness verificado', verify_result.stdout)

            self.run_cmd(['python3', 'scripts/new_ticket.py'], cwd=target, input_text='\n'.join([
                'fix',
                'Repair docs',
                'Need docs repair',
                'Make docs clear',
                'Docs flow',
                'No redesign',
                'low',
                'med',
                'Docs clear',
                'Verify green',
                '',
            ]) + '\n')

            with (target / 'project' / 'README.md').open('a', encoding='utf-8') as fh:
                fh.write('\nchange\n')

            publish_result = self.run_cmd(
                ['python3', 'scripts/publish_ticket.py', '--feature-id', 'F-001'],
                cwd=target,
            )
            self.assertIn('done ->', publish_result.stdout)

            publish_path = target / 'work' / 'artifacts' / 'F-001' / 'publish.json'
            payload = json.loads(publish_path.read_text(encoding='utf-8'))
            self.assertEqual(payload['verdict'], 'PUBLISHED')
            self.assertTrue(payload['pushed'])
            self.assertEqual(payload['remote'], 'origin')

            status_result = self.run_cmd(['git', 'status', '--short'], cwd=target)
            self.assertEqual(status_result.stdout.strip(), '')

            remote_refs = self.run_cmd(['git', 'ls-remote', 'origin'], cwd=target)
            self.assertIn('refs/heads/master', remote_refs.stdout)

    def test_agent_status_rejects_invalid_agent(self):
        result = self.run_cmd(
            ['python3', 'scripts/agent_status.py', 'set', '--agent', 'nope'],
            check=False,
        )
        self.assertNotEqual(result.returncode, 0)
        combined = (result.stdout + result.stderr)
        self.assertIn('Invalid agent: nope', combined)


if __name__ == '__main__':
    unittest.main()
