#!/usr/bin/env python3
"""Локальная организация исследования; сетевых функций нет."""
import argparse, csv, hashlib, json, re, shutil, sys
from pathlib import Path
from datetime import datetime, timezone
ROOT=Path(__file__).resolve().parent.parent

def main():
 p=argparse.ArgumentParser(description=__doc__)
 sub=p.add_subparsers(dest='cmd',required=True)
 q=sub.add_parser('new',help='Создать дело в текущей папке/cases');q.add_argument('name')
 q=sub.add_parser('hash',help='SHA-256 файла или каталога, CSV в stdout');q.add_argument('path',type=Path)
 q=sub.add_parser('urls',help='Извлечь уникальные HTTP(S) URL из локального UTF-8 текста');q.add_argument('file',type=Path)
 a=p.parse_args()
 if a.cmd=='new':
  if not re.fullmatch(r'[A-Za-z0-9][A-Za-z0-9_-]{0,79}',a.name):p.error('Имя: латинские буквы, цифры, _ и -, до 80 символов')
  dest=Path.cwd()/'cases'/a.name
  dest.mkdir(parents=True,exist_ok=False)
  for name in ['originals','working','captures','exports','logs']: (dest/name).mkdir()
  for src in (ROOT/'templates').iterdir():shutil.copy2(src,dest/src.name)
  (dest/'case.json').write_text(json.dumps({'name':a.name,'created_at_utc':datetime.now(timezone.utc).isoformat(),'scope':'Заполните вопрос, период и разрешённый диапазон'},ensure_ascii=False,indent=2))
  print(dest)
 elif a.cmd=='hash':
  base=a.path.resolve(strict=True)
  files=[base] if base.is_file() else sorted(x for x in base.rglob('*') if x.is_file() and not x.is_symlink())
  w=csv.writer(sys.stdout);w.writerow(['path','bytes','sha256'])
  for f in files:
   h=hashlib.sha256()
   with f.open('rb') as stream:
    for chunk in iter(lambda:stream.read(1024*1024),b''):h.update(chunk)
   w.writerow([str(f.name if base.is_file() else f.relative_to(base)),f.stat().st_size,h.hexdigest()])
 elif a.cmd=='urls':
  text=a.file.read_text(encoding='utf-8-sig')
  print('\n'.join(sorted(set(m.rstrip('.,;:!?)]}') for m in re.findall(r'''https?://[^\s<>"']+''',text)))))
if __name__=='__main__':
 try:main()
 except (OSError,ValueError) as e:print(f'Ошибка: {e}',file=sys.stderr);sys.exit(1)
