/* Football Manager Retro 4.2 – tactical training and live match instructions */
(function(){
  'use strict';
  const C=(v,a=0,b=100)=>typeof clamp==='function'?clamp(v,a,b):Math.max(a,Math.min(b,v));
  const R=(a,b)=>typeof rand==='function'?rand(a,b):Math.floor(Math.random()*(b-a+1))+a;
  const LABELS={none:'Keines',penalties:'Elfmeter',freekicks:'Freistöße',corners:'Eckbälle',offside:'Abseitsfalle',pressing:'Pressing',possession:'Ballbesitzspiel',counter:'Konterspiel'};
  try{Object.assign(SPECIAL_TRAINING_LABELS,LABELS);}catch(_e){}

  function ensureTactics(){
    if(!state)return;
    if(typeof ensureAllPlayerDNA==='function')ensureAllPlayerDNA();
    if(typeof ensureV15State==='function')ensureV15State();
    const c=getUserClub();
    c.tacticalStrengths ||= {};
    const t=c.tacticalStrengths;
    if(t.corners===undefined)t.corners=R(52,72);
    if(t.pressing===undefined)t.pressing=R(50,72);
    if(t.possession===undefined)t.possession=R(50,72);
    if(t.counter===undefined)t.counter=R(50,72);
    if(t.offside===undefined)t.offside=c.offsideTrap??R(50,72);
    c.offsideTrap=t.offside;
    state.matchSettings ||= {};
    const defaults={tactic:'balanced',aggression:'normal',tempo:'normal',pressing:'medium',possession:'balanced',transition:'normal',defensiveLine:'middle',instruction:'none'};
    Object.entries(defaults).forEach(([k,v])=>{if(state.matchSettings[k]===undefined)state.matchSettings[k]=v;});
    state.tactics42 ||= {lastTraining:[],version:42};
  }
  function avg(c,key){return Math.round((c.squad||[]).reduce((s,p)=>s+(Number(p[key])||0),0)/Math.max(1,(c.squad||[]).length));}
  function bestPlayer(c,key,positions){return [...(c.squad||[])].filter(p=>!positions||positions.includes(p.position)).sort((a,b)=>(Number(b[key])||0)-(Number(a[key])||0))[0]||c.squad?.[0];}

  const previousTraining=typeof runWeeklyTraining==='function'?runWeeklyTraining:null;
  if(previousTraining){
    runWeeklyTraining=function(){
      ensureTactics();const c=getUserClub(),before={...c.tacticalStrengths},special=state.training?.special||'none';
      previousTraining();
      const t=c.tacticalStrengths,baseChance=state.training?.intensity==='high'?.72:state.training?.intensity==='light'?.36:.54;
      const keyMap={corners:'corners',pressing:'pressing',possession:'possession',counter:'counter',offside:'offside'};
      const key=keyMap[special];
      if(key&&Math.random()<baseChance)t[key]=C(t[key]+R(1,2),30,99);
      c.offsideTrap=t.offside;
      const changes=Object.keys(t).filter(k=>t[k]>before[k]).map(k=>`${({corners:'Eckball',pressing:'Pressing',possession:'Ballbesitz',counter:'Konter',offside:'Abseitsfalle'})[k]} ${before[k]}→${t[k]}`);
      state.tactics42.lastTraining=changes;
      if(changes.length){state.news.unshift(`Taktiktraining: ${changes.join(', ')}`);state.training.lastReport=`${state.training.lastReport} ${changes.join(', ')}.`;}
    };
  }
  const previousCamp=typeof startTrainingCamp==='function'?startTrainingCamp:null;
  if(previousCamp){
    startTrainingCamp=function(){
      ensureTactics();const c=getUserClub(),beforeBalance=c.balance,beforeCooldown=state.training?.campCooldown||0;
      previousCamp();
      if(c.balance<beforeBalance||(state.training?.campCooldown||0)>beforeCooldown){
        Object.keys(c.tacticalStrengths).forEach(k=>c.tacticalStrengths[k]=C(c.tacticalStrengths[k]+R(1,3),30,99));
        c.offsideTrap=c.tacticalStrengths.offside;state.news.unshift('Das Trainingslager verbesserte zusätzlich alle taktischen Mannschaftswerte.');save();render();
      }
    };
  }

  const previousTrainingView=typeof training==='function'?training:null;
  if(previousTrainingView){
    training=function(){
      ensureTactics();let html=previousTrainingView();const c=getUserClub(),t=c.tacticalStrengths;
      // Existing select is rebuilt because older versions only knew three special options.
      html=html.replace(/<select id="specialTraining">[\s\S]*?<\/select>/,`<select id="specialTraining">${Object.entries(LABELS).map(([v,l])=>`<option value="${v}" ${state.training.special===v?'selected':''}>${l}</option>`).join('')}</select>`);
      const tactical=`<div class="card tactics-training-card" style="margin-top:16px"><h2>Mannschaftstaktik & Standards</h2><p class="muted">Standards werden im Spiel automatisch ausgelöst. Das Training verbessert Ausführung, Abläufe und taktische Sicherheit.</p><div class="tactic-strengths tactic-strengths-42">
        <div><span>Elfmeter</span><b>${avg(c,'penalties')}</b></div><div><span>Freistöße</span><b>${avg(c,'freeKicks')}</b></div><div><span>Eckbälle</span><b>${t.corners}</b></div><div><span>Pressing</span><b>${t.pressing}</b></div><div><span>Ballbesitz</span><b>${t.possession}</b></div><div><span>Konter</span><b>${t.counter}</b></div><div><span>Abseitsfalle</span><b>${t.offside}</b></div>
      </div>${state.tactics42.lastTraining?.length?`<div class="news good"><b>Letzte taktische Verbesserungen:</b> ${state.tactics42.lastTraining.map(esc).join(' · ')}</div>`:''}</div>`;
      return html+tactical;
    };
  }

  function ensureLiveSettings(){
    ensureTactics();if(!liveMatch)return;const s=state.matchSettings;
    ['tactic','aggression','tempo','pressing','possession','transition','defensiveLine','instruction'].forEach(k=>{if(liveMatch[k]===undefined)liveMatch[k]=s[k];});
    liveMatch.tacticalStats ||= {homePossession:50,userPressWins:0,userCounters:0,offsides:0,cornersHome:0,cornersAway:0,freeKicksHome:0,freeKicksAway:0,penaltiesHome:0,penaltiesAway:0};
  }
  function option(value,current,label){return `<option value="${value}" ${current===value?'selected':''}>${label}</option>`;}
  function liveControlsHtml(){
    ensureLiveSettings();const l=liveMatch;
    return `<div class="live-tactics tactics-42">
      <label>Grundausrichtung<select id="liveTactic">${option('offensive',l.tactic,'Offensiv')}${option('balanced',l.tactic,'Ausgeglichen')}${option('defensive',l.tactic,'Defensiv')}</select></label>
      <label>Spieltempo<select id="liveTempo">${option('slow',l.tempo,'Langsam')}${option('normal',l.tempo,'Normal')}${option('fast',l.tempo,'Schnell')}</select></label>
      <label>Pressing<select id="livePressing">${option('deep',l.pressing,'Tief stehen')}${option('medium',l.pressing,'Mittleres Pressing')}${option('high',l.pressing,'Hohes Pressing')}</select></label>
      <label>Pass- und Ballbesitzspiel<select id="livePossession">${option('direct',l.possession,'Direktes Spiel')}${option('balanced',l.possession,'Ausgeglichen')}${option('possession',l.possession,'Ballbesitz')}</select></label>
      <label>Umschaltspiel<select id="liveTransition">${option('counter',l.transition,'Auf Konter')}${option('normal',l.transition,'Normal')}${option('control',l.transition,'Kontrolle')}</select></label>
      <label>Zweikampf<select id="liveAggression">${option('fair',l.aggression,'Fair')}${option('normal',l.aggression,'Normal')}${option('hard',l.aggression,'Hart')}</select></label>
      <label>Abwehrlinie<select id="liveDefensiveLine">${option('deep',l.defensiveLine,'Tief')}${option('middle',l.defensiveLine,'Mittel')}${option('high',l.defensiveLine,'Hoch / Abseitsfalle')}</select></label>
      <label>Traineranweisung<select id="liveInstruction">${option('none',l.instruction,'Keine')}${option('wings',l.instruction,'Über Außen')}${option('middle',l.instruction,'Durch die Mitte')}${option('crosses',l.instruction,'Frühe Flanken')}${option('short',l.instruction,'Kurzpassspiel')}${option('long',l.instruction,'Lange Bälle')}${option('shots',l.instruction,'Distanzschüsse')}${option('compact',l.instruction,'Defensiv kompakt')}${option('wide',l.instruction,'Offensiv breit')}</select></label>
    </div><p class="muted tactic-explanation">Pressing, Tempo und harte Zweikämpfe kosten zusätzliche Kondition. Eine hohe Linie nutzt die trainierte Abseitsfalle. Standards werden automatisch berechnet.</p>`;
  }

  const previousLiveView=typeof liveView==='function'?liveView:null;
  if(previousLiveView){
    liveView=function(){
      ensureTactics();let html=previousLiveView();if(!liveMatch||liveMatch.finished)return html;ensureLiveSettings();
      html=html.replace(/<label>Spezialtaktik<select id="liveSpecial">[\s\S]*?<\/select><\/label>/,'');
      // Replace the compact legacy tactics block, preserving formation control and substitutions elsewhere.
      html=html.replace(/<div class="live-tactics">[\s\S]*?<\/div>(?=<div class="substitution-box">)/,liveControlsHtml());
      // Fallback when formation is part of the old block and the regex cannot match.
      if(!html.includes('id="liveTempo"'))html=html.replace('<div class="substitution-box">',liveControlsHtml()+'<div class="substitution-box">');
      const stats=liveMatch.tacticalStats;
      html=html.replace('<div class="grid cols-2 live-layout">',`<div class="card live-tactic-stats"><span>Ballbesitz Heim <b id="livePossessionStat">${Math.round(stats.homePossession)}%</b></span><span>Pressing-Ballgewinne <b>${stats.userPressWins}</b></span><span>Konter <b>${stats.userCounters}</b></span><span>Abseits <b>${stats.offsides}</b></span></div><div class="grid cols-2 live-layout">`);
      return html;
    };
  }

  function eligible(club,kind){
    const pool=(club.squad||[]).filter(p=>(p.injuryGames||0)<=0&&(p.suspensionGames||0)<=0&&p.position!=='TW');
    if(!pool.length)return null;
    return [...pool].sort((a,b)=>{
      if(typeof ensurePlayerDNA==='function'){ensurePlayerDNA(a);ensurePlayerDNA(b);}
      const score=p=>kind==='header'?(p.dna?.heading||p.rating)+(p.dna?.height||178)/10:kind==='shot'?(p.dna?.shotPower||p.rating)+(p.dna?.speed||p.rating)*.25:p.rating;
      return score(b)-score(a);
    })[R(0,Math.min(4,pool.length-1))];
  }
  function userIs(club){return club.id===state.userClubId;}
  function teamTactics(club){
    if(userIs(club)){ensureLiveSettings();return {tactic:liveMatch.tactic,tempo:liveMatch.tempo,pressing:liveMatch.pressing,possession:liveMatch.possession,transition:liveMatch.transition,aggression:liveMatch.aggression,line:liveMatch.defensiveLine,instruction:liveMatch.instruction,trained:getUserClub().tacticalStrengths};}
    return {tactic:'balanced',tempo:'normal',pressing:'medium',possession:'balanced',transition:'normal',aggression:'normal',line:'middle',instruction:'none',trained:{corners:65,pressing:65,possession:65,counter:65,offside:65}};
  }
  function addEvent(club,type,text,p){addLiveEvent(liveMatch.minute,type,text,club.id,p?.id);}
  function scoreGoal(club,p,text){if(club.id===liveMatch.home.id)liveMatch.homeGoals++;else liveMatch.awayGoals++;if(p)p.goals=(p.goals||0)+1;addEvent(club,'goal',text,p);}

  // Final match engine wrapper: tactical settings influence possession, event selection, standards, fatigue and cards.
  if(typeof processLiveMinute==='function'){
    processLiveMinute=function(){
      if(!liveMatch)return;ensureLiveSettings();if(typeof ensureAllPlayerDNA==='function')ensureAllPlayerDNA();const m=liveMatch.minute;
      if(m===45){addLiveEvent(m,'halftime',typeof commentary==='function'?commentary('halftime'):'Halbzeitpfiff.');return;}
      const home=liveMatch.home,away=liveMatch.away,ht=teamTactics(home),at=teamTactics(away),stats=liveMatch.tacticalStats;
      let homeShare=50+(liveMatch.homePower-liveMatch.awayPower)*.35;
      const possessionMod=t=>t.possession==='possession'?(t.trained.possession-50)*.10+5:t.possession==='direct'?-4:0;
      homeShare+=possessionMod(ht)-possessionMod(at);homeShare=C(homeShare,28,72);stats.homePossession=stats.homePossession*.92+homeShare*.08;
      let homeAttack=Math.random()<homeShare/100;let club=homeAttack?home:away,opp=homeAttack?away:home,tac=homeAttack?ht:at,oppTac=homeAttack?at:ht;

      const userAttack=userIs(club),userDefends=userIs(opp);
      const pressingChance=(oppTac.pressing==='high'?.026:oppTac.pressing==='medium'?.011:.003)*(oppTac.trained.pressing/65);
      if(Math.random()<pressingChance){club=opp;opp=homeAttack?away:home;tac=oppTac;homeAttack=club.id===home.id;if(userIs(club))stats.userPressWins++;addEvent(club,'tactic',`Das ${oppTac.pressing==='high'?'hohe':'kompakte'} Pressing erzwingt einen Ballverlust.`);}

      const lineRisk=oppTac.line==='high'?.018:oppTac.line==='deep'?.002:.007;
      if(Math.random()<lineRisk*(oppTac.trained.offside/65)){
        stats.offsides++;addEvent(opp,'tactic',`${opp.name} lässt den Angriff mit der trainierten Abseitsfalle auflaufen.`);return;
      }

      const tempoMod=tac.tempo==='fast'?.014:tac.tempo==='slow'?-.010:0;
      const styleMod=tac.tactic==='offensive'?.011:tac.tactic==='defensive'?-.008:0;
      const counterActive=tac.transition==='counter'&&Math.random()<(.18+tac.trained.counter/250);
      const chanceRate=.035+tempoMod+styleMod+(counterActive?.016:0);
      if(counterActive&&userAttack){stats.userCounters++;addEvent(club,'tactic',`Schneller Konter von ${club.name} – das trainierte Umschaltspiel greift.`);}
      const roll=Math.random();

      // Automatic penalty situations.
      if(roll<.0018){
        const taker=bestPlayer(club,'penalties');const quality=(Number(taker?.penalties)||65)+(taker?.dna?.form||65)*.15;
        if(club.id===home.id)stats.penaltiesHome++;else stats.penaltiesAway++;
        addEvent(club,'chance',`Elfmeter für ${club.name}. ${taker?.name||'Der Schütze'} läuft an.`,taker);
        if(Math.random()<C(.48+quality/230,.55,.90))scoreGoal(club,taker,`TOR! ${taker.name} verwandelt den Elfmeter.`);else addEvent(club,'save',`${taker?.name||'Der Schütze'} scheitert vom Elfmeterpunkt.`,taker);return;
      }
      // Automatic free kicks.
      if(roll<.0065){
        const taker=bestPlayer(club,'freeKicks',['ST','RA','LA','ZM','OM']);const quality=Number(taker?.freeKicks)||60;
        if(club.id===home.id)stats.freeKicksHome++;else stats.freeKicksAway++;
        addEvent(club,'chance',`Freistoß für ${club.name}. ${taker?.name||'Ein Spezialist'} übernimmt.`,taker);
        if(Math.random()<C(.035+quality/900,.07,.17))scoreGoal(club,taker,`Direkter Freistoß! ${taker.name} trifft sehenswert.`);return;
      }
      // Automatic corners, improved by corner training and heading/height.
      if(roll<.017){
        if(club.id===home.id)stats.cornersHome++;else stats.cornersAway++;
        const header=eligible(club,'header');addEvent(club,'corner',`Ecke für ${club.name}. Die trainierte Variante wird ausgeführt.`,header);
        const cornerQuality=tac.trained.corners+(header?.dna?.heading||header?.rating||60)*.45;
        if(header&&Math.random()<C(.025+cornerQuality/1250,.06,.18))scoreGoal(club,header,`${header.name} köpft die Ecke ins Tor!`);return;
      }
      if(roll<chanceRate){
        const wantHeader=tac.instruction==='crosses'||tac.instruction==='wings'||Math.random()<.24;
        const p=eligible(club,wantHeader?'header':'shot');if(!p)return;
        const d=p.dna||{},instructionText=tac.instruction==='middle'?'durch die Mitte':tac.instruction==='wings'?'über den Flügel':tac.instruction==='short'?'nach einer Kurzpasskombination':tac.instruction==='long'?'nach einem langen Ball':tac.instruction==='shots'?'mit einem Distanzschuss':wantHeader?'nach einer Flanke':'mit einem Abschluss';
        addEvent(club,wantHeader?'header':'chance',`${club.name} greift ${instructionText} an. ${p.name} kommt zum Abschluss.`,p);
        let attack=(wantHeader?(d.heading||p.rating)+(d.height||180)*.12:(d.shotPower||p.rating)+(d.speed||p.rating)*.22)+(d.form||65)*.22+p.rating*.35;
        if(counterActive)attack+=(d.speed||p.rating)*.16+tac.trained.counter*.12;
        if(tac.tempo==='fast')attack+=3;if(tac.tactic==='offensive')attack+=3;if(oppTac.line==='deep'&&counterActive)attack-=7;
        const defending=(typeof teamPower==='function'?teamPower(opp):opp.rating)*1.35+R(-16,18)+(oppTac.tactic==='defensive'?5:0)+(oppTac.instruction==='compact'?4:0);
        const finish=C(.12+(attack-defending)/180,.055,.52);
        if(Math.random()<finish)scoreGoal(club,p,`TOR für ${club.name}! ${p.name} nutzt die taktisch herausgespielte Chance.`);else addEvent(club,'save',`Der Torwart pariert gegen ${p.name}.`,p);
      }else{
        const cardBase=tac.aggression==='hard'?.011:tac.aggression==='fair'?.0028:.0055;
        if(Math.random()<cardBase){const p=eligible(club,'shot');if(p){p.yellowCards=(p.yellowCards||0)+1;addEvent(club,'yellow',`Gelbe Karte für ${p.name}.`,p);}}
      }
      // Tactical fatigue every ten minutes.
      if(m>0&&m%10===0){
        [home,away].forEach(team=>{const tt=teamTactics(team),drain=(tt.tempo==='fast'?2:0)+(tt.pressing==='high'?2:tt.pressing==='medium'?1:0)+(tt.aggression==='hard'?1:0);if(drain&&userIs(team)){(liveMatch.userXI||state.selectedXI||[]).map(id=>team.squad.find(p=>p.id===id)).filter(Boolean).forEach(p=>p.fitness=C(p.fitness-R(0,drain),35,100));addEvent(team,'tactic',`Das intensive Spiel kostet sichtbar Kondition.`);}});
      }
    };
  }

  function bindSelect(id,key){const el=document.querySelector(id);if(el)el.onchange=e=>{ensureLiveSettings();liveMatch[key]=e.target.value;state.matchSettings[key]=e.target.value;save();};}
  const previousBind=typeof bindDynamic==='function'?bindDynamic:null;
  if(previousBind){
    bindDynamic=function(){previousBind();if(!state)return;ensureTactics();bindSelect('#liveTempo','tempo');bindSelect('#livePressing','pressing');bindSelect('#livePossession','possession');bindSelect('#liveTransition','transition');bindSelect('#liveDefensiveLine','defensiveLine');bindSelect('#liveInstruction','instruction');const ag=document.querySelector('#liveAggression');if(ag)ag.onchange=e=>{liveMatch.aggression=e.target.value;state.matchSettings.aggression=e.target.value;save();};};
  }
  const previousNew=typeof newGame==='function'?newGame:null;
  if(previousNew)newGame=function(...args){previousNew(...args);ensureTactics();save();render();};
  const previousLoad=typeof load==='function'?load:null;
  if(previousLoad)load=function(){previousLoad();if(state){ensureTactics();save();render();}};
  const previousRender=typeof render==='function'?render:null;
  if(previousRender)render=function(){if(state)ensureTactics();previousRender();const label=document.querySelector('#seasonLabel');if(label&&state)label.textContent=label.textContent.replace(/Version\s+[\d.]+(?:\s+·\s+[^·]+)?/,'Version 4.2 · Taktik & Spielstil');};
})();
